C++ Constructors have no return type. Just exactly

2020-03-01 10:03发布

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.

8条回答
家丑人穷心不美
2楼-- · 2020-03-01 10:10

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楼-- · 2020-03-01 10:11

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

查看更多
戒情不戒烟
4楼-- · 2020-03-01 10:11

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楼-- · 2020-03-01 10:13

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

I believe that all functions have to return something

void?

查看更多
三岁会撩人
6楼-- · 2020-03-01 10:14

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.

查看更多
forever°为你锁心
7楼-- · 2020-03-01 10:19

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.

查看更多
登录 后发表回答