problems with Move constructor and Move overloaded assignment operator?
Solution 1:
Your class A
has several issues:
-
Your assignment operator don't handle self assignment and leak:
A& A::operator=(const A& a) { std::cout<<"overload operator=\n"; if (this != &a) { p = a.p; delete[] s; s = new char[strlen(a.s) + 1]; strcpy(s, a.s); } return *this; }
-
Your move doesn't move but copy:
A::A(A&& a) : p(a.p), s(a.s)
{
a.s = nullptr;
std::cout << "Move constructor\n";
}
A& A::operator=(A&& a)
{
std::cout << "Move overload operator=\n";
if (this != &a) {
p = a.p;
delete [] s;
s = a.s;
a.s = nullptr;
}
return *this;
}
Now, about
A make_A()
{
A a(2,"bonapart"); // Constructor
return a;
}
There are several scenario because of potential copy elision (NRVO)
(gcc has flag as -fno-elide-constructors
to control that)
if NRVO apply, then a
is construct "in-place" so no extra destruction/move happens;
else there is a move constructor and the destruction of a
.
A make_A()
{
A a(2,"bonapart"); // #2 ctor(int const char*)
return a; // #3 move (elided with NRVO)
} // #4 destruction of a, (elided with NRVO)
int main()
{
A a1; // #1: default ctor
a1 = // #5: Move assignment (done after make_A)
make_A(); // #6: destructor of temporary create by make_A
a1.display();
} // #8: destructor of a1
With NRVO
default ctor
ctor(int const char*)
move assignment
destructor
display
destructor
without NRVO (-fno-elide-constructors
)
default ctor
ctor(int const char*)
move ctor
destructor
move assignment
destructor
display
destructor
Demo
For
A a1,a2;
a2 = a1 = make_A();
a1 = make_A();
use move assignment.
a2 = (a1 = make_A())
use copy assignment as move assignment returns (correctly) A&
4 In Move constructor and Move overloaded = operator I used
a.s=nullptr;
This statement is always used in Move semantics fredoverflow(user) explained something like "now the source no longer owns the object it" but I am not getting it. Because if I did not write this statement still no problem everything works fine. please explain this point
Your issue is that you do copy instead of move.
If you do s = a.s;
instead of the copy
s = new char[strlen(a.s) + 1];
strcpy(s, a.s);
then both this->s
and a.s
would point of same data, and both this
and a
would free the (same) memory in their destructor -> double free error.
a.s = nullptr;
would fix that issue.