构造函数或复制构造函数

constructor or copy constructor?

本文关键字:构造函数 复制      更新时间:2023-10-16

泛型编程与STL(中文版)一书中说:

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

我觉得有点奇怪。我写了一个像这样的测试程序

#include <iostream>
class Test {
public:
    Test() {
        std::cout << "This is ctorn";
    }
    Test(const Test&) {
        std::cout << "This is copy-ctorn";
    }
};
int main(int argc, char** argv)
{
    Test t = Test();
    return 0;
}

输出为"This is tor"。好吧,现在我很困惑,哪个是对的?

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

然而,在实践中,副本可以优化出—尽管它有副作用(控制台输出):

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

和(结合同一子句中的例子):

[n3290: 12.2/2]:[…]实现可能会使用临时的in在使用X的副本将X(2)传递给f()之前构造X(2)构造函数;或者,可以在空间中构建X(2)用来举行辩论。[. .]

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

无论如何,如果您在编译时关闭了优化(或者,使用GCC,可能是-fno-elide-constructors),您将看到:

This is ctor
This is copy-ctor

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

在实践中,编译器被允许跳过复制构造部分,直接默认构造x(正如David在他的注释中指出的那样,这仍然要求复制构造函数在语法上是可访问的)。大多数编译器至少在启用优化时是这样做的。

在这种情况下,一种形式的返回值优化(RVO)(也称为Copy Elision)可以在优化方面提供很大帮助。链接的维基百科页面有很好的解释。