2

I wrote the following code:

#include <iostream>

class A
{
public:
    A(){ std::cout << "created" << std::endl; }
    A(A& other) { std::cout << "copied" << std::endl; }
    A& get(){ std::cout <<"got" << std::endl; return *this; }
    ~A(){ std::cout << "destroyed" << std::endl; }
};

Now, lines

A a = A().get();

and

A a;    
a = A();

compile and work correctly, but

A a = A();

claims:

no matching function for call to ‘A::A(A)’
note: candidates are: A::A(A&)
note:                 A::A()

And to make things explicit,

A a = (A&)A();

claims:

error: invalid cast of an rvalue expression of type ‘A’ to type ‘A&’

I completely don't understand this behaviour.

P.S. I know, that if I make const reference in copy c_tor, everything will be OK.

3 Answers 3

3

The copy constructor should get its argument as a const reference (or a simple A value). In your current setup, the program would have to make a mutable reference to a temporary, which is invalid.

Sign up to request clarification or add additional context in comments.

2 Comments

You know, g++ does not think so sometimes. For exasmple, private member of type std::auto_ptr<std::string> will make g++ create default copy c_tor with non-const reference
@Lol4t0: It is OK to have a copy ctor taking a non-const reference; the problem arrives when you try to use it with something that cannot be converted into a non-const ref, such as in this example.
3

This is simple: a rvalue (i.e. something that must be on the right hand side of an equal sign), can convert to a constant reference or be copied. Only a lvalue (i.e. something that can be placed on the left of an equal sign) can be converted into a non-constant reference. The reason being that you may be tempted to modify the content of the non-constant reference, which would be invalid.

A() is a rvalue, and therefore cannot be converted into a non-constant reference. This is your error.

2 Comments

Ok,but why c_tor return r-value? I can call members of that r-value, and I can even write A() = A(); :) More, why does my get() function work? And If you look output, you can see, that no object is removed twice
Oh,It seems also, that r-value can_be l-value
2
A a = A();

This line tries to call the copy-constructor passing a temporary object, and the copy-constructor takes argument by non-const reference. But a temporary object cannot be bound to a non-const reference. That is why you get the compilation error.

However, a temporary object can be bound to const reference. So, the solution is to make the parameter const reference as:

A(const A& other) { std::cout << "copied" << std::endl; }

1 Comment

this explanation sounds most logical for me

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.