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

11

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

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

Кто говорит, что конструктор - это функция? (Помимо того, что это описано в стандартном разделе «Специальные функции-члены») Ben Voigt
AFAIK возвращает новый созданный объект. Tamer Shlash
Из любопытства, когда было бы полезно или вообще иметь смысл, чтобы конструктор возвращал что-либо кроме объекта, который он строит? kevin628

Ваш Ответ

8   ответов
13

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

10

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

и то, что Внешний вид как вызов конструктора на самом деле приведени Ben Voigt
@ downvoter, пожалуйста, объясни свой голос dasblinkenlight
8

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

void?

Конструкторы даже не возвращаютvoid (если это имеет смысл). У них нет типа возврата. David Hammen
@ DavidHammen Тот факт, что конструкторы не могут быть вызваны, и что они определены, чтобы ничего не возвращать, не дает реализациям такую широту. Правило «как будто» делает это. Реализации могут привести к тому, что вызываемые функции, возвращающие значение, будут «возвращать» другие вещи, если они ведут себя в соответствии со стандартом. bames53
@ DavidHammen Это только разница в синтаксисе. Объявление типа возвращаемого значения функции какvoid имеет то же значение. bames53
Разница только в синтаксисе? Конструктор является пустой функцией в том смысле, что оператор возврата должен бытьreturn; в конструкторе. Однако, делая конструктор не вызываемым и оставляя тип возвращаемого значения неопределенным, стандарт, по-видимому, позволяет поставщику компилятора иметь конструктор, возвращающий что-то, пока он действует так, как будто он возвращает void. David Hammen
@ DavidHammen: вы уверены, что у них нет типа возврата? Насколько я понимаю, у них нетназвани и тип возврата такой же, как у класса. Единственное отличие состоит в том, что body вернет void, и все равно результатом оценки будет данный ти lorro
1

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

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

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

1

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

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

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

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

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

Тот факт, что конструкторы ничего не возвращают, не имеет никакого отношения к тому, можете ли вы вызывать конструктор. Вы не можете вызвать конструктор, потому что у конструкторов нет имени, и нет синтаксиса для его вызова. (Только обходной путь; размещение нового). bames53
0

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

2

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

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 ++ мешает отсутствие такого правила?

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

возможно, плохое имя для этого. Это практически инициализатор для предварительно построенных объектов. Самый простой способ проиллюстрировать это - псевдо-пример для эквивалентной конструкции без использования конструкторов 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, у которых нет ничего, что могло бы помочь программисту подобным образом.

Похожие вопросы