[英]C++: which is the appropriate constructor to be called: the constructor or the copy constructor?
编码
class ElisionTest
{
public:
int n;
// ElisionTest(ElisionTest& other): n(other.n) {cout<<"copy constructor"<<endl;}
ElisionTest(int n): n(n) {cout<<"constructor"<<endl;}
};
int main(int argc, char const *argv[])
{
ElisionTest et = 10;
}
打印"constructor"
,这很好。 现在,当我取消注释复制构造函数时,我得到一个编译时错误:
cpp_test.cpp: In function 'int main(int, const char**)':
cpp_test.cpp:140:19: error: no matching function for call to 'ElisionTest::ElisionTest(ElisionTest)'
cpp_test.cpp:140:19: note: candidates are:
cpp_test.cpp:135:2: note: ElisionTest::ElisionTest(int)
cpp_test.cpp:135:2: note: no known conversion for argument 1 from 'ElisionTest' to 'int'
cpp_test.cpp:134:2: note: ElisionTest::ElisionTest(ElisionTest&)
cpp_test.cpp:134:2: note: no known conversion for argument 1 from 'ElisionTest' to 'ElisionTest& {aka ElisionTest&}'
这可能会继续表明这里将使用临时ElisionTest(10)
调用复制构造函数。 并且由于您不能对临时引用非const引用,因此使复制构造const&
的参数成为const&
应解决错误。
但是,如果我修改复制构造函数以获取const ElisionTest&
而不是ElisionTest&
,则没有错误,输出又是"constructor"
。 为什么不打印"copy constructor"
?
ElisionTest(ElisionTest& other);
具有该签名的构造函数允许通过左值初始化ElisionTest
实例。 当你这样做:
ElisionTest et = 10;
这将从临时构造ElisionTest
的实例。 您的代码相当于:
ElisionTest et = ElisionTest(10);
这将调用构造函数,该构造函数接受非const引用并使用它初始化et
。 但是非const引用不能绑定到临时引用。 这就是为什么我们需要将const
添加到你的拷贝构造函数中,以便它可以支持左值和右值:
ElisionTest(ElisionTest const& other);
// ^^^^^
你没有看到输出的原因是因为称为copy-elision的东西。 编译器可以省略对复制/移动构造函数的调用。 在GCC中,您可以使用-fno-elide-constructors
-elide -fno-elide-constructors
来关闭copy-elision。
它输出"constructor"
因为它需要从10
转换为ElisionTest
。
它也没有打印"copy constructor"
因为它已经被优化了(复制省略)。 这是允许改变程序的可观察行为的唯一可能的优化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.