4

当我在这里阅读有关复制初始化与直接初始化的信息时。复制构造函数应该调用复制初始化。为什么这里复制构造函数不调用?

#include <iostream>

using namespace std;

class A{};

class B{
public:
B(const A &a){cout << "B construct from A" << endl;}
B(const B &b){cout << "B copy constructor" << endl;}
};

int main(){
A a;
B b = a;
return 0;
}
4

2 回答 2

5

复制初始化仍然受到复制省略的影响,我猜这就是正在发生的事情。从理论上讲,临时B构造是从临时构造的,a并且复制构造函数用于b从临时构造中创建。在实践中,副本可以被优化出来。

要对此进行测试,您可以将复制构造函数设为私有:

class B{
public:
B(const A &a){cout << "B construct from A" << endl;}
private:
B(const B &b){cout << "B copy constructor" << endl;}
};

并得到一个编译错误。这意味着编译器期望复制构造函数可以访问,但不需要调用它。

复制省略是唯一可以改变观察到的行为的情况。

于 2012-10-02T07:30:57.890 回答
5

这是复制省略参考 1:。
编译器可以通过内联创建对象来优化生成临时对象时的复制构造函数调用,并且 C++ 标准明确允许这样做。

这在标准中也通过示例很好地证明了这一点:

C++03 标准 12.2 临时对象 [class.temporary]
第 2 段:

[Example:
class X {
    // ...
    public:
    // ...
    X(int);
    X(const X&);
    ˜X();
};
X f(X);

void g()
{
    X a(1);
    X b = f(X(2));
    a = f(a);
}

X(2)在这里,一个实现可能会在将它传递给f()使用 X 的复制构造函数之前使用一个临时对象来构造它;或者,X(2)可以在用于保存论点的空间中构造。此外,在将结果f(X(2))复制到`b usingX ’s copyconstructor; alternatively,f() ’s result might be constructed in b. On the other hand, the expressiona=f(a) requires a temporary for either the argument a or the result off(a) to avoid undesired aliasing ofa` 之前,可能会使用一个临时值来保存结果。]

参考 1:
C++03 12.8 复制类对象 [class.copy]
第 12 段:

当满足某些条件时,允许实现省略类对象的复制构造,即使对象的复制构造函数和/或析构函数具有副作用......

于 2012-10-02T07:36:48.330 回答