Вопрос по constructor, c++ – Конструкторы C ++ не имеют возвращаемого типа. Просто почему?
==========================================================================================

 Я гуглил это и прочитал много постов, но есть так много разных ответов, что все логично, что мне было интересно, может ли эксперт по этой теме демистифицировать этот вопрос.

 Некоторые говорят, что нет возврата, потому что нет способа вернуть - синтаксис запрещает это - да, это имеет смысл, но я считаю, что все функции должны что-то возвращать, нет? Другие говорят, что конструктор как бы возвращает сам вновь созданный объект, что, кажется, имеет смысл, поскольку в конструкторе используется оператор присваивания. У других есть и другие интересные объяснения.

 поэтому они не возвращаются как другие функции. Они выполняются как побочный эффект определенных конструкций (приведение,`new`, определение переменной, Т е р-инициализатора-лист, передача по значению, возврат по значению).



 потому что он будет избыточным: нет другого типа, кроме того, который создается, который конструктор мог бы потенциально «вернуть». Я помещаю «return» в кавычки, потому что технически конструкторы ничего не возвращают: когда они вызываются в статическом контексте, они инициализируют экземпляр на месте; когда они вызываются в динамическом контексте, это оператор`new`, который возвращает что-то, а не конструктор.



 

 Я считаю, что все функции должны что-то возвращать

`void`?



 

No. Что значит вернуть значение из функции? Хорошо, ABI для реализации будет указывать, что для некоторого возвращаемого типа функция будет устанавливать определенные регистры или некоторую память с некоторым смещением от указателя стека на значение, которое «возвращает» функци

 Очевидно, что регистры и память существуют и содержат данные после вызова конструктора или функции void, но язык говорит, что эти функции ничего не возвращают, и поэтому ABI не указывает, какие регистры или память следует искать, чтобы найти возвращаемое значение. , Код не может установить возвращаемое значение, а вызывающий код может получить любое возвращаемое значение.

 Нет, функции не должны ничего возвращать.



 У конструкторов нет возвращаемого типа - даже`void` - означает, что вы не можете вызвать конструктор из своего кода C ++. И в этом все дело. Вызов конструктора не имеет смысла. Недопустимость вызова конструктора исключает саму возможность такого типа ошибки пользователя.

**Редактироват**

barnes прав в том, что главная причина, по которой вы не можете вызывать конструкторов, заключается в том, что у них нет имени. (И даже при этом игнорируется, что вы можете вызывать конструктор косвенно через размещение нового.)

 Пытаясь снова:

 Вы не можете вызывать конструкторы из своего кода C ++, потому что у конструкторов нет имени. Создание конструкторов, не имеющих возвращаемого типа, подчеркивает программисту, что конструкторы - это совсем другой тип функций, чем другие функции. Что на самом деле возвращает конструктор, если он что-то возвращает, зависит от поставщика.



иворечить, если оно предназначено для возврата чего-либо, а программист вернет что-то совершенно иное, чем сам класс. В основном, синтаксис будет сбивать с толку.



 что конструкторы могут что-то возвращать, это может привести к проблемным последствиям для следующего вызова функции:

```
class Object{ 
    public: 
        bool Object(){ ... };   
        ...
}      

SomeFun(Object obj){ ... } 

SomeFun(Object());   
// Ha! SomeFun jokes on an error about a non-Object argument(of type bool), returned  
// by the anonymous temporary Object()

```
 Предотвращение возврата функций конструктора, облегчает использование анонимных временных файлов, а также многие другие функции C ++. Без такого правила безобидные заявления могут стать неоднозначными:

```
Object obj(Object()); 
// How does the variable obj decide which constructor to call,  
// based on its argument type?  
// 
// Does it call: bool Object::Object(Object&) or  
//                    Object::Object(bool)(if it exists)? 

```
 Способность конструкторов возвращать значение усложняет создание объектов - наличие единственного однозначного типа, имени класса, при отсутствии произвольных возвращаемых значений позволяет избежать таких проблем.

 Могут ли читатели предложить дополнительные примеры, когда идиомам C ++ мешает отсутствие такого правила?



 возможно, плохое имя для этого. Это практически инициализатор для предварительно построенных объектов. Самый простой способ проиллюстрировать это - псевдо-пример для эквивалентной конструкции без использования конструкторов C ++.

 С конструкторами

```
struct X {
    int a;
    X() {
      a = -5;
    }
};

int main() {
    X* x1 = new X(); // X created as a "reference object".
    X  x2;           // X created as a "value object" on the stack.
    return x1->a - x2.a;
}

```
 Без конструкторов

```
struct X {
    int a;
    void initialize() {
        a = -5;
    }
    static X* create() {
        X* res = (X*)malloc(sizeof(X));
        res->initialize();
        return res;
    }
};

int main() {
    X* x1 = X::create(); // New constructed heap-allocated X
    X  x2;               // Stack-allocated X
    x2.initialize();     // Manually initialized
    return x1->a - x2.a;
}

```
 Теперь, если ты представишь это`X::initialize` во втором примере нужно было вернуться, скажем,`bool` указывает на успех или неудачу, у вас возникнут проблемы. В`main()`, невнимательный программист может закончить с`X`, который не инициализирован должным образом, что приводит к неопределенному поведению (обычно сложный для отладки сбой, который может не быть обнаружен до производства).

 Это одна из основных причин, почему конструкторы становятся особенными. Единственный способ выйти из конструктора - через обычное завершение или исключение, котороедолже затем будет обработан вызывающим (или передан вверх по стеку). В любом случае вы предотвращаете попадание неинициализированных объектов.

 Как примечание, неинициализированные объекты являются одной из наиболее распространенных причин ошибок в C, у которых нет ничего, что могло бы помочь программисту подобным образом.