2

I have the following code:

#include<iostream>
using namespace std;
class A{
    int size;
    double *arr;

public:
    A(int len):size(len)
    {
        cout<<"ctor called"<<endl;
        arr=new double[size];
    }
    A(const A &rhs)
    {
        cout<<"calling copy ctor"<<endl;
        size=rhs.size;
        arr=new double[size];
    }
    A(A&& rhs)
    {
      cout<<"caling move constructor"<<endl;
      size=rhs.size;
      arr=rhs.arr;
      rhs.arr=nullptr;
    }
    ~A()
    {
        cout<<"Calling Dtor"<<endl;
        delete[] arr;
        size=0;
        arr=NULL;
    }
};
A createVector()
{
    cout<<"Creating object"<<endl;
    A a(20);
    cout<<"returning after creating object a"<<endl;
    return (a);
}
void foo(A v)
{
    cout<<"Class A object rcvd"<<endl;
    return;
}
int main()
{
    //cout<<"a has been rcvd"<<endl;
    foo(createVector());
    return 0;
}

I have passed a temporary object of Type 'A'(which has been returned by another function).I am expecting a call to Move constructor.But I am getting the below output:

Creating object
ctor called
returning after creating object a
Class A object rcvd
Calling Dtor

Why there is no call to Move Constructor?? Also if change the code as following:

foo(createVector())----->foo(move(createVector()));

I get the following output:

Creating object
ctor called
returning after creating object a
caling move constructor
Class A object rcvd
Calling Dtor
Calling Dtor

Why there is a call to Destructor two times??

aalisha
  • 41
  • 8
  • 1
    Different question but same answer as your last question (see 1st comment): https://stackoverflow.com/questions/51336284/why-copy-constructor-not-called – Richard Critten Jul 14 '18 at 11:17
  • Count of constructors calls = count of destructors calls – acade Jul 14 '18 at 11:51
  • @acade constructor is called once.In move constructor ,I just changed changed the pointer,I did not created any object. – aalisha Jul 14 '18 at 12:07
  • when you calls move constructor you creates new object, but old object **remains**. Old object has null values, but it **exists** – acade Jul 14 '18 at 12:18
  • This doesn't address the question, but `size = 0; arr = NULL;` in the destructor is pointless. The object is going away; those members won't exist after the destructor exits. – Pete Becker Jul 14 '18 at 12:37
  • @acade As per you ,calling move constructor will create new object which means its constructor should be called,then whats the point of introducing move semantics anyway?? – aalisha Jul 14 '18 at 13:21
  • @PeteBecker I agree,as I am full time C programmer,I am quite used to with these notations.(dangling pointer).:P – aalisha Jul 14 '18 at 13:25
  • Related: https://stackoverflow.com/questions/48749440/c-nrvo-copy-elision-with-return-statement-in-parentheses. Possibly a bug. – xskxzr Jul 14 '18 at 15:38

1 Answers1

2

Why there is no call to Move Constructor??

There is no call to the move constructor because movement has been optimized away. When createVector creates its A object, it does not create the object in the usual place for local variables. Instead, the object is created in the usual place for the returned value. This returned value goes to the place that main designated for it, namely its "temporary object of Type 'A'". Since this temporary is being passed by value to another function, it is constructed in the usual place for such parameters.

So, when createVector creates its A object named a, the location of a is already the correct location for being passed by main to foo, no moving required (until you explicitly request a move). Rejoice! Your compiler is being efficient! Ignore it and move on to more important concerns. (If this is more than an attempt to understand move semantics, you are probably writing bad code.)

Why there is a call to Destructor two times??

Because you forced two objects into existence. In this case, the temporary object returned by createVector was forced into a different location than the object used as a parameter to foo. Both need to be destroyed. (Moving from an object potentially leaves that object in an unusable state, but it is still an object that needs to be destroyed. The unusable state does need to be coherent enough for the destructor to handle.)

JaMiT
  • 14,422
  • 4
  • 15
  • 31