C++ Constructors have no return type. Just exactly

2020-03-01 10:18发布

问题:

I've Googled this and read many posts, but there are so many different answers that all make logical sense that I was wondering if an expert on the topic could demystify this question.

Some say that there is no return because there is no way to return - the syntax prohibits it - yes, this makes sense, but I believe that all functions have to return something, no? Others say that the constructor sort of returns the newly created object itself, which seems to make sense since the assignment operator is used on the constructor. Still others have other interesting explanations.

回答1:

Constructors aren't called like other functions, so they don't return like other functions. They execute as a side-effect of certain constructs (cast, new, variable definition, ctor-initializer-list, pass-by-value, return-by-value).



回答2:

The constructor does not specify a return type because it would be redundant: there is no type other than the one being constructed that a constructor could potentially "return". I put "return" in quotes because technically constructors do not return anything: when they are invoked in a static context, they initialize an instance in place; when they are invoked in a dynamic context, it is the operator new that returns something, not a constructor.



回答3:

The constructor constructs in-place, it has no need to return anything.

I believe that all functions have to return something

void?



回答4:

Assuming constructors could return something, then this has problematic implications for the following function call:

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()

Preventing constructor functions from returning, facilitates the use of anonymous temporaries, along with many more C++ features. Without such a rule, innocuous statements can become ambiguous:

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)? 

The ability for constructors to return a value, complicates the creation of objects - having a single unambiguous type, the class name, in the absence of arbitrary return values, avoids such problems.

Can readers suggest further examples where C++ idioms are hindered by the absence of such a rule?



回答5:

but I believe that all functions have to return something, no?

No. What does it mean to return a value from a function? Well, the ABI for an implementation will specify that for some return type a function will set certain registers, or some memory at some offset from the stack pointer, to the value that is 'returned' by the function.

Obviously registers and memory exist and contain data after a constructor or void function is called, but the language says those functions don't return anything, and so the ABI doesn't specify which registers or memory to look in to find a return value. The code can't set a return value and calling code can get any return value.

So no, functions don't have to return anything.



回答6:

That constructors lack a return type -- not even void -- means that you can't call a constructor from your C++ code. And that's the point. Calling a constructor doesn't make sense. Making it illegal to call a constructor eliminates the very possibility of this type of user error.

Edit

barnes is right in that the ultimate reason you can't call constructors is that they have no name. (And even this ignores that you can call a constructor indirectly via placement new.)

Trying again:

You can't call constructors from your C++ code because constructors don't have a name. Making constructors not have a return type emphasizes to the programmer that constructors are a very different kind of function than other functions. What a constructor actually does return, if it returns anything, is up to the vendor.



回答7:

Constructors are perhaps a bad name for it. It is practically an initializer for pre-constructed objects. Easiest way to illustrate this is a pseudo-example for the equivalent construct without using the C++ constructors.

With constructors

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;
}

Without constructors

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;
}

Now, if you imagine that X::initialize in the second example were to be made to return, say a bool indicating success or failure, you would have a problem. In main(), the inattentive programmer might end up with an X that isn't properly initialized, leading to undefined behavior (usually a hard-to debug crash that might not be discovered before production).

This is one of the core reasons why constructors are made special. The only two ways to exit a constructor, is through normal completion, or through an exception, which must then be handled by the caller (or passed on up the stack). In any case, you prevent ending up with uninitialized objects.

As a side-note, uninitialized objects are one of the more common causes of bugs in C, which does not have anything to help the programmer like this.



回答8:

Constructors implicitly return an instance of the class itself. It will be contradicting if it were designed to return something and the programmer returned something completely different other than the class itself. Basically the syntax would be confusing.