简体   繁体   English

C ++:这是要调用的适当构造函数:构造函数还是复制构造函数?

[英]C++: which is the appropriate constructor to be called: the constructor or the copy constructor?

The code 编码

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;

}

prints "constructor" and that's fine. 打印"constructor" ,这很好。 Now, when I uncomment the copy constructor, I get a compile time error: 现在,当我取消注释复制构造函数时,我得到一个编译时错误:

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&}'

Which probably goes on to show that here the copy constructor will be called with a temporary ElisionTest(10) . 这可能会继续表明这里将使用临时ElisionTest(10)调用复制构造函数。 And since you can't have a non-const reference to a temporary, making the argument of the copy constructor a const& should resolve the error. 并且由于您不能对临时引用非const引用,因此使复制构造const&的参数成为const&应解决错误。

But, if I modify the copy constructor to take const ElisionTest& instead of ElisionTest& , there's no error and the output is "constructor" again. 但是,如果我修改复制构造函数以获取const ElisionTest&而不是ElisionTest& ,则没有错误,输出又是"constructor" Why didn't it print "copy constructor" ? 为什么不打印"copy constructor"

ElisionTest(ElisionTest& other);

A constructor with that signature allows the initialization of an ElisionTest instance through an lvalue. 具有该签名的构造函数允许通过左值初始化ElisionTest实例。 When you do this: 当你这样做:

ElisionTest et = 10;

This will construct an instance of ElisionTest from a temporary. 这将从临时构造ElisionTest的实例。 Your code is equivalent to: 您的代码相当于:

ElisionTest et = ElisionTest(10);

This will call your constructor that takes a non-const reference and initialize et with that. 这将调用构造函数,该构造函数接受非const引用并使用它初始化et But a non-const reference cannot be bound to a temporary. 但是非const引用不能绑定到临时引用。 That's why we will need to add const to your copy-constructor so that it can support both lvalues and rvalues: 这就是为什么我们需要将const添加到你的拷贝构造函数中,以便它可以支持左值和右值:

ElisionTest(ElisionTest const& other);
//                      ^^^^^

The reason you are seeing no output is because of something called copy-elision . 你没有看到输出的原因是因为称为copy-elision的东西。 The compiler can omit the call to the copy/move constructor. 编译器可以省略对复制/移动构造函数的调用。 In GCC, you can use -fno-elide-constructors to turn off copy-elision. 在GCC中,您可以使用-fno-elide-constructors -elide -fno-elide-constructors来关闭copy-elision。

It outputs "constructor" because it needs to convert from 10 to ElisionTest . 它输出"constructor"因为它需要从10转换为ElisionTest

It didn't also print "copy constructor" because it got optimized away (copy elision). 它也没有打印"copy constructor"因为它已经被优化了(复制省略)。 That's the only possible optimization that is allowed to alter the observable behavior of a program. 这是允许改变程序的可观察行为的唯一可能的优化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM