Pergunta

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. 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). 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.

But, if I modify the copy constructor to take const ElisionTest& instead of ElisionTest&, there's no error and the output is "constructor" again. Why didn't it print "copy constructor"?

Foi útil?

Solução

ElisionTest(ElisionTest& other);

A constructor with that signature allows the initialization of an ElisionTest instance through an lvalue. When you do this:

ElisionTest et = 10;

This will construct an instance of ElisionTest from a temporary. 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. But a non-const reference cannot be bound to a temporary. That's why we will need to add const to your copy-constructor so that it can support both lvalues and rvalues:

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

The reason you are seeing no output is because of something called 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.

Outras dicas

It outputs "constructor" because it needs to convert from 10 to ElisionTest.

It didn't also print "copy constructor" because it got optimized away (copy elision). That's the only possible optimization that is allowed to alter the observable behavior of a program.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top