为什么这段代码无法编译?如果我将复制构造函数访问级别更改为public,它就可以并打印“Foo :: Foo(int)”。如果我写“Foo instance(0);”而不是“Foo instance = 0;”它也没关系。为什么?这种行为有什么意义呢?
#include <iostream>
struct Foo
{
public:
int i;
Foo(int i) : i(i) { std::cout << "Foo::Foo(int) \n"; }
private:
Foo(const Foo&) { std::cout << "Foo::Foo(const Foo&) \n"; }
};
int main()
{
Foo instance = 0;
}
答案 0 :(得分:2)
Foo instance = 0;
使用复制初始化。 0
使用非显式构造函数Foo
转换为Foo(int i)
对象,然后将其复制为instance
。它相当于:
Foo instance = Foo(0);
这需要您私有的复制构造函数。
当你公开它时,转换构造函数打印但复制构造函数不打印的原因是编译器可以省略该副本以进行优化。这是一种可能会改变代码执行的优化形式。然而,复制构造函数仍然需要公开,无论它是否被省略。换句话说,副本需要在可以省略之前完成。
如果你制作转换构造函数explicit
,它将无法编译:
explicit Foo(int i) : i(i) { std::cout << "Foo::Foo(int) \n"; }
答案 1 :(得分:1)
因为
Foo instance = 0;
是复制初始化,需要一个可访问的复制构造函数。它尝试使用转换构造函数从Foo
创建临时0
,然后使用复制构造函数从临时instance
创建Foo
。
相比之下,
Foo instance(0);
是直接初始化,只需要转换构造函数。
相关:What's the motivation behind having copy and direct initialization behave differently?