构造函数或复制构造函数?

时间:2011-08-25 12:05:33

标签: c++ constructor copy-constructor

Generic Programming和STL (中文版)一书中,它说:

  

X x = X()将调用复制构造函数。

对我来说似乎有点奇怪。我写了一个像这样的测试程序

#include <iostream>

class Test {

public:

    Test() {
        std::cout << "This is ctor\n";
    }

    Test(const Test&) {
        std::cout << "This is copy-ctor\n";
    }

};

int main(int argc, char** argv)
{

    Test t = Test();
    return 0;
}

输出为“This is ctor”。好的,现在我很困惑,这是对的吗?

3 个答案:

答案 0 :(得分:9)

Nomimally yes,临时是默认构造的,然后调用复制构造函数将其复制到对象t中。

但是,实际上可以优化副本 - ,即使它有副作用(控制台输出):

  

[n3290: 8.5/16]:[..]在某些情况下,实施是   允许消除此中固有的复制   通过直接构造中间结果直接初始化   进入被初始化的对象;见12.2,12.8。

并且(与同一条款中给出的例子一起):

  

[n3290: 12.2/2]:[..]一个实现可能会使用临时的   在使用X的副本将其传递给f()之前构造X(2)   构造函数;或者,X(2)可以在空间中构建   曾经持有这个论点。 [..]

但是复制构造函数 仍然必须存在,即使它可能没有被调用。

无论如何,如果你在关闭优化的情况下编译(或者,使用GCC,可能是-fno-elide-constructors),你会看到:

This is ctor
This is copy-ctor

答案 1 :(得分:4)

理论上,X x = X()将调用默认构造函数来创建临时对象,并使用复制构造函数将其复制到x

实际上,允许编译器直接跳过复制构造部分和default-construct x(正如David在他的评论中指出的那样,仍然需要复制构造函数在语法上可访问)。大多数编译器至少在启用优化时执行此操作。

答案 2 :(得分:2)

这种形式的Return Value Optimisation(RVO)(也称为Copy Elision)可以帮助您进行优化。链接的维基百科页面对正在发生的事情有很好的解释。