Mostly all things explained by fredoverflow(user 237K Rep.) in his Two answers
But while implementing Move constructor and overloaded Move Assignment operator(OMAO
)( I am using these short form throughout the question ) I am facing some problem that I will put here.
Also there is another answer by user Greg Hewgill (user with 826K Rep.)
https://mcmap.net/q/15702/-what-is-move-semanticshis
I am Quoting him,
Suppose you have a function that returns a substantial object then an ordinary C++ compiler will create a temporary object for the result of multiply(), call the copy constructor to initialize r, and then destruct the temporary return value. Move semantics in C++0x allow the "move constructor" to be called to initialize r by copying its contents, and then discard the temporary value without having to destruct it.
I will also refer this in question.
okay Now I will start
Code
.cpp
#include"34_3.h"
#include<iostream>
#include<conio.h>
#include<cstring>
A::A() // O arg ctor
{
std::cout<<"0 arg constructor\n";
p=0;
s=nullptr;
}
A::A(int k1,const char *str) // 2 arg ctor
{
std::cout<<"2 arg constructor\n";
p=k1;
s=new char[strlen(str)+1];
strcpy(s,str);
}
A::A(const A &a) // copy ctor
{
std::cout<<"copy constructor\n";
p=a.p;
s=new char[strlen(a.s)+1];
strcpy(s,a.s);
}
A::A(A &&a) // Move ctor
{
std::cout<<"Move constructor\n";
p=a.p;
s=new char[strlen(a.s)+1];
strcpy(s,a.s);
a.s=nullptr;
}
A& A::operator=(const A &a) // Overloaded assignement opeator `OAO`
{
std::cout<<"overloade= operator\n";
p=a.p;
s=new char[strlen(a.s)+1];
strcpy(s,a.s);
return *this;
}
A& A::operator=(A &&a) // `OMAO`
{
std::cout<<"Move overloade = operator\n";
p=a.p;
s=new char[strlen(a.s)+1];
strcpy(s,a.s);
a.s=nullptr;
return *this;
}
A::~A() // Dctor
{
delete []s;
std::cout<<"Destructor\n";
}
void A::display()
{
std::cout<<p<<" "<<s<<"\n";
}
.h
#ifndef header
#define header
struct A
{
private:
int p;
char *s;
public:
A(); // 0 arg ctor
A(int,const char*); // 2 arg ctor
A(const A&); // copy ctor
A(A&&); // Move ctor
A& operator=(const A&); // `OAO`
A& operator=(A&&); // `OMAO`
~A(); // dctor
void display(void);
};
#endif
I am putting few main functions and their outputs here so I can discuss the problem easily.
1_main
A make_A();
int main()
{
A a1=make_A();
a1.display();
}
A make_A()
{
A a(2,"bonapart");
return a;
}
Output
2 arg constructor
2 bonapart
Destructor
- why it is not executing Move constructor but if I commented out Move constructor definition in .cpp file and declaration in .h file then it give error
[Error] no matching function for call to 'A::A(A)'
and if I use thisA a1=std::move(make_A());
then Move constructor calls, So why this happening ? - Why destructor for object
a
in make_A() function is not running ?
2_main()
A make_A();
int main()
{
A a1;
a1=make_A();
a1.display();
}
A make_A()
{
A a(2,"bonapart");
return a;
}
Output
0 arg ctor
2 arg ctor
Move overloade = operator
copy ctor
Dctor
Dctor
2 bonapart
Dctor
- Now here copy constructor and destructor runs for temporary object created due to return *this from Move overload = operator function. According to Greg Hewgill statement
C++ 0x
allows Move constructor to be called to initialize by copying it's contents and then discard the temporary value without having to destruct it. I am usingC++11
but still initializing is done by creating temporary object, copy constructor. - I am not getting for which object that 2nd destructor is running?
3_main
fredoverflow (user 237K Rep.) kept return type of Move overloaded operators A&
but I think it is wrong.
A make_A();
int main()
{
A a1,a2;
a2=a1=make_A();
a1.display();
a2.display();
}
A make_A()
{
A a(2,"bonapart");
return a;
}
Output
[Error] prototype for 'A& A::operator=(A&&)' does not match any in class 'A'
so I feel return type should be A&&
or A
but A&&
too give error [ERROR] can't bind a lvalue to a&&
so return type must be A
, am I right ?
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
this
, not just"ctor"
or"dtor"
. Thethis
value will give you a much better indication of what object is printing those lines. – Caryncaryoa.s=nullptr;
. That will lead to a leak since the memory allocated fora
is not longer free'd. You should "move" the pointers instead, not reallocate and copy (that's what the copy constructor and assignment operators do). For example by just swapping the pointers:std::swap(s, a.s);
(But remember to initializes
tonullptr
first in the constructor). – Gingerlya1
by which we called Move overloaded operator but what that means – YolandayolandeA a1(std::move(make_A()));
orA a1=std::move(make_A());
to make it called explicitly – Interlarda
which is declared inMake_A()
fun. some guy commented me that is extension of life, en.cppreference.com/w/cpp/language/copy_elision NRVO happens but I did not understand it. and you mentioned aboutswap
there is no another way to do this ? – YolandayolandeA a1=std::move(make_A())
will call the Move constructor but whyA a1=make_A(); not calls the Move constructor but actually it stores that value when I check it by display function. I listened about
std::move` first time can you explain it please or give some link where it explained. – Yolandayolandedisplay()
, so drop that. This allows dropping all data members fromA
, which in turn makes the member functions so simple that they might as well be defined inline. Poof! No more .cpp file. – Torp