Why userdefined move constructor is not called in below example? - c++

I am expecting that after using std::move(any_object) we are converting that object in rvalue reference and due to this it should call my userdefined move constructor. but it is not working like this.Could anyone tell whats happening?
#include <iostream>
#include <memory>
struct Demo {
int Value;
Demo():Value(10) { std::cout << "Demo's default constructor called\n";}
Demo(Demo& tempObj) { std::cout << "Demo non-const copy constructor called\n";}
Demo(const Demo& tempObj) { std::cout << "Demo const copy constructor called\n"; }
Demo(Demo&& tempObj) { std::cout << "Demo move constructor called\n"; }
Demo(const Demo&& tempObj) { std::cout << "Demo const move constructor called\n"; }
Demo& operator= (const Demo& tempObj){ std::cout << "Demo copy assignment operator called ";}
Demo& operator= (Demo&& tempObj){ std::cout << "Demo move assignment operator called";}
~Demo(){ std::cout << "Demo's destructor called\n";}
};
void fun(Demo&& tempObj)
{
tempObj.Value = 20;
}
int main()
{
Demo demo;
fun(std::move(demo));
}
//output:
Demo's default constructor called
Demo's destructor called

Why userdefined move constructor is not called in below example?
Because you're only binding an rvalue reference to an xvalue and not actually constructing an instance of type Demo. That is, a move constructor will be called when you actually construct an instance of type Demo using a rvalue as shown below for example:
//-----------v-------->removed && from here
void fun(Demo tempObj)
{
tempObj.Value = 20;
}
fun(std::move(demo)); //now this uses move constructor
Additionally, you missing return statement in your assignement operators.

Related

Copy constructor is being called first instead of only move constructor on passing even R-value reference

Hello! I am making my own string class named strings
On passing a R-value move constructor and move assignment operator are being called
This is the main function, all i am doing is passing R-value ref, but while debugging only copy are or both move and copy.
int main()
{
strings s1="hey!";
cout<<"\n";
s1=strings("bye");
cout<<"\n";
s1="Hello";
cout<<"\n";
strings s2= strings{"Rhythm"};
s2.print();
return 0;
}
//move comstructor
strings::strings(strings &&obj):s{obj.s}
{
std::cout<<"Calling move const\n";
obj.s=nullptr;
}
//move assinment operator
strings& strings::operator=(strings &&obj)
{
std::cout<<"Using move\n";
if(this==&obj){
return *this;
}
delete[] s;
s=obj.s;
obj.s=nullptr;
return *this;
}
//copy constructor;
strings::strings(const strings &obj)
{
s=new char[strlen(obj.s)+1];
strcpy(this->s,obj.s);
}
An moving assignment (not an assignment initialization) requires a move operator=(strings&&). It is not available if you defined own copy constructor. Note, that in situation like this
struct S {
S() {}
S(const S &obj) { std::cout << "Copy ctor" << std::endl;}
S(S &&obj) { std::cout << "Move ctor" << std::endl;}
S& operator=(const S &obj) { std::cout << "Copy =" << std::endl; return *this;}
S& operator=(S &&obj) { std::cout << "Move =" << std::endl; return *this;}
};
int main()
{
S a = S();
a = S();
}
with C++11 compiler the declaration line wouldn't even produce output, because no copy or move did happen, it was elided.

Clang-Tidy: Move constructor initializes class member by calling a copy constructor

class Vtx {
private:
int indexPoint;
int radius;
std::string strName;
public:
Vtx(const int p_indexPoint, const int p_radius, std::string p_strName)
: indexPoint(p_indexPoint),
radius(p_radius),
strName(std::move(p_strName)) {
std::cout << "Constructor\n";
}
Vtx(const Vtx& rhs)
: indexPoint(rhs.indexPoint),
radius(rhs.radius),
strName(rhs.strName) {
std::cout << "Copy constructor\n";
}
// (#)
Vtx(const Vtx&& rhs)
: indexPoint(rhs.indexPoint),
radius(rhs.radius),
strName(rhs.strName) {
std::cout << "Move constructor\n";
}
~Vtx() {
std::cout << "Destructor\n";
}
};
For this code, clang-tidy gives me following warning message.
Move constructor initializes class member by calling a copy constructor
I can't understand when the copy constructor is called inside of move constructor.(#) Although compilation works well, but I want to remove this warning. How to I fix it?
You forget to move the members (can be omitted for built-in type where move is copy anyway)
and also moving from const object is generally a copy so you have to change to
Vtx(Vtx&& rhs)
: indexPoint(rhs.indexPoint),
radius(rhs.radius),
strName(std::move(rhs.strName)) {
std::cout << "Move constructor\n";
}
Note that, in your case, except for message (you can move that code in dedicated class to ease Vtx implementation BTW), default implementation would be ok:
Vtx(Vtx&& rhs) = default;

What Constructor is being called, it's not move

I created a basic test class to learn how the move constructor works. The move constructor does not seem to be called, and I'm not sure what constructor is actually called. If I use std::move then the move constructor is called, but a regular R value won't actually call it. Why is this happening, and what constructor is actually being called? I'm using g++ 4.6.3
#include <iostream>
#include <cstring>
class Test
{
int a;
int b;
int* c;
public:
Test(int one, int two)
{
std::cout << "Param Constructor" << "\n";
a = one;
b = two;
}
Test()
{
std::cout << "Default Constructor" << "\n";
a = 1;
b = 2;
}
~Test()
{
std::cout << "Deconstructor" << "\n";
}
Test(const Test& test)
{
a = test.a;
b = test.b;
std::cout << "Copy constructor called" << "\n";
}
Test(Test&& test)
{
std::cout << "Move constructor called" << "\n";
a = test.a;
b = test.b;
}
Test& operator=(const Test& test)
{
std::cout << "in operator=" << "\n";
a = test.a;
b = test.b;
return *this;
}
};
Test createTest()
{
return Test(1,2);
}
int main()
{
Test test(createTest());
Test test2 = test;
std::cout << "After logic" << "\n";
return 0;
}
The output I get:
Param Constructor
Copy constructor called
After logic
Deconstructor
Deconstructor
I create an object of type Test with the name test, but there is no output of it being created? I was expecting this output:
Param Constructor
Move Constructor // (Missing)
Deconstructor //Deleting instance from createTest (Missing)
Copy constructor called
After logic
Deconstructor
Deconstructor
what constructor is actually being called?
No constructor at all. Count the number of destructor calls. You'll find that there is one less than you expected. The temporary that you expected to be constructed wasn't created at all.
Why is this happening
The compiler avoided creation of the temporary. Instead, the object was constructed in place where it would have been moved to otherwise. This is known as copy elision.

Why is the copy constructor called in this code after the assignment operator?

If I modify the assignment opreator so that it returns an object A instead of a reference to an object A then something funny happens.
Whenever the assignment operator is called, the copy constructor is called right afterwards. Why is this?
#include <iostream>
using namespace std;
class A {
private:
static int id;
int token;
public:
A() { token = id++; cout << token << " ctor called\n";}
A(const A& a) {token = id++; cout << token << " copy ctor called\n"; }
A /*&*/operator=(const A &rhs) { cout << token << " assignment operator called\n"; return *this; }
};
int A::id = 0;
A test() {
return A();
}
int main() {
A a;
cout << "STARTING\n";
A b = a;
cout << "TEST\n";
b = a;
cout << "START c";
A *c = new A(a);
cout << "END\n";
b = a;
cout << "ALMOST ENDING\n";
A d(a);
cout << "FINAL\n";
A e = A();
cout << "test()";
test();
delete c;
return 0;
}
The output is as follows:
0 ctor called
STARTING
1 copy ctor called
TEST
1 assignment operator called
2 copy ctor called
START c3 copy ctor called
END
1 assignment operator called
4 copy ctor called
ALMOST ENDING
5 copy ctor called
FINAL
6 ctor called
test()7 ctor called
Because if you don't return a reference of the object it makes a copy.
As #M.M said about the final test() call, the copy does not appears because of the copy elision What are copy elision and return value optimization?

Why isn't move constructor invoked?

Here is the code: http://coliru.stacked-crooked.com/a/f7731b48747c61a9
#include <iostream>
struct A{
A(const A&){ std::cout << "A(const A&)" << std::endl;}
A(const A&&){ std::cout << "A(const A&&)" << std::endl;}
A(){ }
};
A foo(){
return *new A;
}
int main()
{
A a;
A c(foo());
}
Since, I passed to the c's constructor argument a temporary object, I expected the move constructor to be called. But the copy constructor was. Why?
Since foo returns a non-constant rvalue, it cannot bind to the const-rvalue reference. The copy constructor is the only remaining viable overload.
A constructor that would be a better overload than the copy constructor would be:
A(A&&);
Additionally, either constructor (copy or move) may be elided under the rules of copy elision (e.g. see here or here.)