I've found strange behavior of a code which is apparently ignoring const-ness:
#include <iostream>
using std::cerr;
class A
{
public:
A() { cerr << "A::A()\n"; }
A(const A &a) { cerr << "A::A(const A&)\n"; }
A(A &&) { cerr << "A::A(A&&)\n"; }
A & operator = (const A &a) { cerr << "A::operator=(const A&)\n"; return *this; }
A & operator = (A &&a) { cerr << "A::operator(A&&)\n"; return *this; }
~A() { cerr << "A::~A()\n"; }
const A get() const { cerr << "const A A::get() const\n"; return A(); }
A get() { cerr << "A A::get()\n"; return A(); }
};
int main()
{
const A a;
A b = a.get();
}
Firstly, what I did expect here: a
is a constant, so the constant-version of get() is invoked. Next, constant object is being returned, but on the left side is non-constant object b
, so the copy-constructor is ought to be called. Which is not:
A::A()
const A A::get() const
A::A()
A::~A()
A::~A()
Is this behavior expected by c++ standard? So, is it okay that constness of a temporary object is simply ignored by RVO? And how copying could be enforced here?
Output with copy-elision disabled (-fno-elide-constructors
) makes an additional move and the expected copy-constructor call:
A::A()
const A A::light_copy() const
A::A()
A::A(A&&)
A::~A()
A::A(const A&)
A::~A()
A::~A()
A::~A()
If a
object is not constant, then it will be two moves without copying, which is expected too.
PS. The behavior matters for me because the one I see is breaking shallow-copying const-strictness: for const-version of get()
(which is shallow_copy()
actually) I need to be sure that no modification of the returned object will be made, because the returned object is a shallow copy and a modification on the shallow copy will affect the "parent" object (which might be a constant).
Aucun commentaire:
Enregistrer un commentaire