C ++构造函数没有返回类型。究竟是为什么?

时间:2012-04-27 18:42:57

标签: c++ compiler-construction constructor return

我用谷歌搜索了这篇文章并阅读了很多帖子,但是有很多不同的答案都有逻辑意义,我想知道这个话题的专家是否可以揭开这个问题的神秘面纱。

有人说没有回报因为无法返回 - 语法禁止它 - 是的,这是有道理的,但我相信所有功能必须返回一些东西,不是吗? 其他人说构造函数的类型返回新创建的对象本身,这似乎是有意义的,因为赋值运算符在构造函数上使用。 还有一些人有其他有趣的解释。

8 个答案:

答案 0 :(得分:13)

构造函数不像其他函数一样被调用,因此它们不会像其他函数一样返回。它们作为某些结构(强制转换,new,变量定义, ctor-initializer-list ,按值传递,按值返回)的副作用执行。

答案 1 :(得分:10)

构造函数没有指定返回类型,因为它是多余的:除了正构造的构造函数可能“返回”之外,没有其他类型。我将“return”放在引号中,因为技术上构造函数不会返回任何内容:当它们在静态上下文中调用时,它们会初始化一个实例;当它们在动态上下文中被调用时,运算符new返回一些东西,而不是构造函数。

答案 2 :(得分:8)

构造函数就地构造,不需要返回任何内容。

  

我相信所有功能都必须返回一些东西

void

答案 3 :(得分: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 ++成语因缺乏这样的规则而受阻?

答案 4 :(得分:1)

构造函数缺少返回类型 - 甚至不是void - 意味着您无法从C ++代码中调用构造函数。这就是重点。调用构造函数没有意义。将调用构造函数设置为非法会消除此类用户错误的可能性。

修改

巴恩斯是正确的,因为你不能称之为建设者的最终原因是他们没有名字。 (甚至忽略了你可以通过放置new来间接调用构造函数。)

再试一次:

您无法从C ++代码中调用构造函数,因为构造函数没有名称。使构造函数没有返回类型强调程序员构造函数是一种与其他函数完全不同的函数。构造函数实际返回的内容,如果返回任何内容,则取决于供应商。

答案 5 :(得分:1)

  

但我相信所有功能都必须返回一些东西,不是吗?

没有。从函数返回值是什么意思?好吧,实现的ABI将指定对于某些返回类型,函数会将某些寄存器或某些与堆栈指针偏移的内存设置为函数“返回”的值。

显然,在调用构造函数或void函数之后,寄存器和内存存在并包含数据,但语言表示这些函数不返回任何内容,因此ABI没有指定要查找的寄存器或内存回报价值。代码无法设置返回值,调用代码可以获得任何返回值。

所以不,函数不必返回任何东西。

答案 6 :(得分: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中更常见的错误原因之一,它没有任何东西可以帮助这样的程序员。

答案 7 :(得分:0)

构造函数隐式返回类本身的实例。如果它被设计为返回某些东西并且程序员返回除了类本身之外完全不同的东西,那将是矛盾的。基本上语法会令人困惑。