在 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”。好的,现在我很困惑,这是对的吗?
答案 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)可以帮助您进行优化。链接的维基百科页面对正在发生的事情有很好的解释。