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://stackoverflow.com/a/3106136/11862989his
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
";
p=0;
s=nullptr;
}
A::A(int k1,const char *str) // 2 arg ctor
{
std::cout<<"2 arg constructor
";
p=k1;
s=new char[strlen(str)+1];
strcpy(s,str);
}
A::A(const A &a) // copy ctor
{
std::cout<<"copy constructor
";
p=a.p;
s=new char[strlen(a.s)+1];
strcpy(s,a.s);
}
A::A(A &&a) // Move ctor
{
std::cout<<"Move constructor
";
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
";
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
";
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
";
}
void A::display()
{
std::cout<<p<<" "<<s<<"
";
}
.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