Почему нельзя писать void ctor();
От: Максим Рогожин Россия  
Дата: 21.04.17 06:56
Оценка:
Привет всем!

Почему нельзя писать так

class A {
public:
   void A() {}
};

?

Отличается ли из-за этого низкоуровневая организация вызова этой функции (организация стека, пролог, эпилог)?
Re: Почему нельзя писать void ctor();
От: SaZ  
Дата: 21.04.17 08:09
Оценка:
Здравствуйте, Максим Рогожин, Вы писали:

МР>Привет всем!


МР>Почему нельзя писать так


МР>
МР>class A {
МР>public:
МР>   void A() {}
МР>};

МР>?

МР>Отличается ли из-за этого низкоуровневая организация вызова этой функции (организация стека, пролог, эпилог)?


Потому что конструктор не возвращает значений. В том числе типа void. Да, void тоже имеет тип.
Re: Почему нельзя писать void ctor();
От: Videoman Россия https://hts.tv/
Дата: 21.04.17 08:29
Оценка:
Здравствуйте, Максим Рогожин, Вы писали:

МР>Привет всем!


МР>Почему нельзя писать так


МР>
МР>class A {
МР>public:
МР>   void A() {}
МР>};

МР>?

Как уже ответили он не имеет возвращаемого типа, совсем никакого.
Т.е. вот так написать можно:
void FuncA();
void FuncB() 
{
return FuncA();
}

а вот так нельзя:
class A
{
//...
};
void FuncB()
{
return A();
}
Отредактировано 21.04.2017 8:35 Videoman . Предыдущая версия .
Re: Почему нельзя писать void ctor();
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 21.04.17 08:50
Оценка: 2 (1)
Здравствуйте, Максим Рогожин, Вы писали:

МР>Почему нельзя писать так


МР>class A {

МР>public:
МР> void A() {}
МР>};
МР>?

Страуструп писал, что это для подчёркивания того факта, что конструктор никогда не зовётся напрямую.

МР>Отличается ли из-за этого низкоуровневая организация вызова этой функции (организация стека, пролог, эпилог)?


Вот принятое в Unix ABI, например, знает

  <ctor-dtor-name> ::= C1    # complete object constructor
           ::= C2    # base object constructor
           ::= C3    # complete object allocating constructor
           ::= D0    # deleting destructor
           ::= D1    # complete object destructor
           ::= D2    # base object destructor


В этом случае тот конструктор, что с C3, аллоцирует память и возвращает адрес объекта, а те, что C1 и C2, получают первым скрытым параметром адрес объекта и ничего не возвращают.

Больше отличий нет, остальное идентично обычной функции.

Для MSVC правил не знаю, могут быть хитрости.
The God is real, unless declared integer.
Re[2]: Почему нельзя писать void ctor();
От: Максим Рогожин Россия  
Дата: 21.04.17 08:59
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Т.е. вот так написать можно:

V>
V>void FuncA();
V>void FuncB() 
V>{
V>return FuncA();
V>}
V>

V>а вот так нельзя:
V>
V>class A
V>{
V>//...
V>};
V>void FuncB()
V>{
V>return A();
V>}
V>


Это понятно. Но я думал, что void как раз и означает что функция не возвращает СОВСЕМ НИКАКОГО значения. Это не так? Раз это не так, то отличается ли организация вызова конструктора от вызова обычных функций, например таких:

int f(int x) { return x*x; }
void g() { return; }


Я имею ввиду является ли трансляция C++ вызова конструктора в ассемблерный код каким-то специальным частным случаем, который обрабатывается способом отличным от способа, которым транслируются вышеприведенные функции int f(int) и void g(), например?
Re[2]: Почему нельзя писать void ctor();
От: Максим Рогожин Россия  
Дата: 21.04.17 09:07
Оценка:
Здравствуйте, SaZ, Вы писали:

SaZ>Потому что конструктор не возвращает значений. В том числе типа void. Да, void тоже имеет тип.


А вот функция

int g(void) { 
   return 0;
}

принимает какие-нибудь значения? Нет. Так в чем разница между void и отсутствием значений (возвращаемых или принимаемых)?
Re[3]: Почему нельзя писать void ctor();
От: rg45 СССР  
Дата: 21.04.17 09:10
Оценка: 2 (1)
Здравствуйте, Максим Рогожин, Вы писали:

МР>Это понятно. Но я думал, что void как раз и означает что функция не возвращает СОВСЕМ НИКАКОГО значения. Это не так? Раз это не так, то отличается ли организация вызова конструктора от вызова обычных функций, например таких:

МР>
МР>int f(int x) { return x*x; }
МР>void g() { return; }
МР>

МР>Я имею ввиду является ли трансляция C++ вызова конструктора в ассемблерный код каким-то специальным частным случаем, который обрабатывается способом отличным от способа, которым транслируются вышеприведенные функции int f(int) и void g(), например?

Говорить об организации вызова и кодогенерации можно лишь в привязке к каким-то конкретным компиляторам и платформам. То есть это уже детали реализации, но никак не свойства самомго языка, описанные в стандарте. Исходя из самых общих соображений, вряд ли можно придумать какие-то причины, по которым кодогенерация конструктров может принципиально отличаться от кодогенерации функций с типом результата void. При этом синтаксис и семантика имеют известные существенные отличия.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 21.04.2017 9:12 rg45 . Предыдущая версия .
Re[3]: Почему нельзя писать void ctor();
От: Videoman Россия https://hts.tv/
Дата: 21.04.17 09:26
Оценка: 2 (1)
Здравствуйте, Максим Рогожин, Вы писали:

МР>Это понятно. Но я думал, что void как раз и означает что функция не возвращает СОВСЕМ НИКАКОГО значения. Это не так? Раз это не так, то отличается ли организация вызова конструктора от вызова обычных функций, например таких:


Это просто синтаксис. Ну вот хотел создатель зачем-то подчеркнуть, что конструктор это не функция и сделал чтобы он не мог участвовать с синтаксических конструкциях с void.

МР>Я имею ввиду является ли трансляция C++ вызова конструктора в ассемблерный код каким-то специальным частным случаем, который обрабатывается способом отличным от способа, которым транслируются вышеприведенные функции int f(int) и void g(), например?


Может является, а может и нет. Вы можете посмотреть ассемблерный листинг, если интересно.
Re[2]: Почему нельзя писать void ctor();
От: Максим Рогожин Россия  
Дата: 22.04.17 07:57
Оценка:
Здравствуйте, netch80, Вы писали:

N>Страуструп писал, что это для подчёркивания того факта, что конструктор никогда не зовётся напрямую.


Мужики, еще немного занудства) Учитывая все сказанное, а почему тогда разрешен следующий синтаксис?

class A {
public:
   A(int);
};

A obj = A(1024);

Глядя на эту запись можно подумать, что здесь конструктор именно зовется напрямую и возвращает значение, аналогично записи

A obj = createObject(1024);
Re[3]: Почему нельзя писать void ctor();
От: rg45 СССР  
Дата: 22.04.17 09:34
Оценка:
Здравствуйте, Максим Рогожин, Вы писали:

МР>
МР>A obj = A(1024);
МР>

МР>Глядя на эту запись можно подумать, что здесь конструктор именно зовется напрямую и возвращает значение, аналогично записи
МР>
МР>A obj = createObject(1024);
МР>


Эти две записи похожи лишь формально. Только в первом случае это является не возвращением значения, а прямым конструированием объекта в правой части инициализатора. Это то же самое выражение, которое используется в операторе return в функции createObject:

A createObject(int value)
{
  return A(value);
}
--
Справедливость выше закона. А человечность выше справедливости.
Re[3]: Почему нельзя писать void ctor();
От: Masterspline  
Дата: 22.04.17 09:55
Оценка:
МР>Я имею ввиду является ли трансляция C++ вызова конструктора в ассемблерный код каким-то специальным частным случаем, который обрабатывается способом отличным от способа, которым транслируются вышеприведенные функции int f(int) и void g(), например?

Функция она и в Африке функция, даже если она — конструктор. Отличаются они только соглашениями вызова функций. Вот посмотри тут, например, calling conventions. Для конструктора нет особого типа функции, т.е. это примерно то, что ты думаешь. Однако, как тут уже указали, синтаксис и семантика конструктора отличаются от обычной функции, поэтому, реализация тоже может отличаться. В результате реализаций конструкторов несколько (опять же как уже написали) с выделением памяти, без него, другие варианты. Таким образом, в коде конструктора оказывается не только тот код, который написан в исходном файле.

P.S. Для виртуальных функций, кстати, тоже нет "особого" типа. Вполне себе обычные функции-члены, только у каждого класса есть еще таблица виртуальных функций (в стандарте реализация не прописана, но все компиляторы делают через таблицу виртуальных функций).
Отредактировано 22.04.2017 10:00 Ssd13 . Предыдущая версия .
Re[3]: Почему нельзя писать void ctor();
От: Максим Рогожин Россия  
Дата: 22.04.17 11:25
Оценка:
Для чего запрещать конструктору возвращать даже void, но при этом разрешать следующий синтаксис?

class A {
public:
  A(int);
};

A obj = A(1024);
Re[4]: Почему нельзя писать void ctor();
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 23.04.17 05:43
Оценка:
Здравствуйте, Максим Рогожин, Вы писали:

МР>Для чего запрещать конструктору возвращать даже void, но при этом разрешать следующий синтаксис?


МР>class A {

МР>public:
МР> A(int);
МР>};

МР>A obj = A(1024);


А почему этот синтаксис надо запрещать? Вы тут создали безымянный объект типа A и затем скопировали его в obj. Это другое, чем просто написать A obj(1024);.

Компилятор, скорее всего, соптимизирует это в простую инициализацию (если ему не запретить созданием своих конструкторов копирования и перемещения, или введением в A нетривиальных полей), но это не меняет, что изначально это разные вещи.
The God is real, unless declared integer.
Re[5]: Почему нельзя писать void ctor();
От: Максим Рогожин Россия  
Дата: 24.04.17 11:26
Оценка:
Здравствуйте, netch80, Вы писали:

N>А почему этот синтаксис надо запрещать?


Потому, что конструктор это функция, которая не возвращает никаких значений. Вот, например

void createObject(int index) {
   A(index); 
}

A obj = createObject(1024); // так же нельзя написать.
A obj = A(1024);            // значит и так нельзя писать... Потому, что функция-конструктор,
                            // с точки зрения синтаксиса, похожа на функцию createObject(int) тем, 
                            // что у нее нет возвращаемого значения.
Re[6]: Почему нельзя писать void ctor();
От: rg45 СССР  
Дата: 24.04.17 14:42
Оценка:
Здравствуйте, Максим Рогожин, Вы писали:

N>>А почему этот синтаксис надо запрещать?

МР>Потому, что конструктор это функция, которая не возвращает никаких значений. Вот, например
МР>
МР>A obj = A(1024);            // значит и так нельзя писать... Потому, что функция-конструктор,
МР>                            // с точки зрения синтаксиса, похожа на функцию createObject(int) тем, 
МР>                            // что у нее нет возвращаемого значения.
МР>


Ты сам себя загоняешь в заблуждение, пытаясь рассматривать это выражение как значение, возвращаемое функцией. В то время как никто никого здесь не возвращает — это прямое конструировние объекта имя типа которого задается конструктором. Это по смыслу то же самое что и
int obj = int(1024);

Нет здесь никакого возвращаемого значения, видишь?

Сам по себе конструктор — это всего лишь процедура, единственная задача которой сконструировать объкт в заданной области памяти. Указатель на эту область памяти передается конструктору неявно, и доступна эта область памяти внутри конструктора как this. Никаких значений он возвращать не может в принципе, потому что один и тот же конструктор может вызываться:

для создания rvalue объекта во временной области памяти:
const auto& obj = A(1024);
aFunction(A(1024) + A(42));

в статической или автоматической:
A obj(1024);

в динамической:
A* obj = new A(1024);

а также в любой неизвестной:
new(aPointer) A(1024);

И это все одна и та же процедура! Как она может что-то возвращать при таком разнообразии сценариев использования?
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 24.04.2017 15:19 rg45 . Предыдущая версия . Еще …
Отредактировано 24.04.2017 15:18 rg45 . Предыдущая версия .
Отредактировано 24.04.2017 15:11 rg45 . Предыдущая версия .
Отредактировано 24.04.2017 14:42 rg45 . Предыдущая версия .
Re[2]: Почему нельзя писать void ctor();
От: MShura  
Дата: 24.04.17 17:15
Оценка:
N>Для MSVC правил не знаю, могут быть хитрости.

В MSVC конструктор возвращает указатель на себя (в rax)
Re[7]: Почему нельзя писать void ctor();
От: CRT  
Дата: 25.04.17 13:16
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, Максим Рогожин, Вы писали:


N>>>А почему этот синтаксис надо запрещать?

МР>>Потому, что конструктор это функция, которая не возвращает никаких значений. Вот, например
МР>>
МР>>A obj = A(1024);            // значит и так нельзя писать... Потому, что функция-конструктор,
МР>>                            // с точки зрения синтаксиса, похожа на функцию createObject(int) тем, 
МР>>                            // что у нее нет возвращаемого значения.
МР>>


R>Ты сам себя загоняешь в заблуждение, пытаясь рассматривать это выражение как значение, возвращаемое функцией. В то время как никто никого здесь не возвращает — это прямое конструировние объекта имя типа которого задается конструктором.


Это выглядит как значение возвращенное функцией. А затем присвоенное с помощью оператора присвоения.
По идее, такое конструирование — это избыточность в языке, достаточно было оставить
A obj(1024);


И эта избыточность запутывает
Отредактировано 25.04.2017 13:19 CRT . Предыдущая версия . Еще …
Отредактировано 25.04.2017 13:19 CRT . Предыдущая версия .
Отредактировано 25.04.2017 13:17 CRT . Предыдущая версия .
Re[4]: Почему нельзя писать void ctor();
От: Erop Россия  
Дата: 25.04.17 19:55
Оценка:
Здравствуйте, rg45, Вы писали:

R>Говорить об организации вызова и кодогенерации можно лишь в привязке к каким-то конкретным компиляторам и платформам. То есть это уже детали реализации, но никак не свойства самомго языка, описанные в стандарте. Исходя из самых общих соображений, вряд ли можно придумать какие-то причины, по которым кодогенерация конструктров может принципиально отличаться от кодогенерации функций с типом результата void. При этом синтаксис и семантика имеют известные существенные отличия.


Есть конструкторы полей и баз, в том числе и виртуальных, соответственно, есть порядок вызова и обработка исключений во всех этих конструкторах, всего этого нет в обычной функции/методе.
Кроме того, соглашение о вызове у метода и функции обычно разные, у деструктора/конструктора они тоже могут быть своими, особенными...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Почему нельзя писать void ctor();
От: Erop Россия  
Дата: 25.04.17 20:02
Оценка:
Здравствуйте, netch80, Вы писали:

N>Компилятор, скорее всего, соптимизирует это в простую инициализацию (если ему не запретить созданием своих конструкторов копирования и перемещения, или введением в A нетривиальных полей), но это не меняет, что изначально это разные вещи.


В этом месте компилятор всегда может пропускать конструктор копии, но обязан проверять его доступность...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: Почему нельзя писать void ctor();
От: Erop Россия  
Дата: 25.04.17 20:09
Оценка:
Здравствуйте, rg45, Вы писали:

R>И это все одна и та же процедура! Как она может что-то возвращать при таком разнообразии сценариев использования?


Ещё создание поля, базы и элемента массива забыл.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.