Search code examples
c++c++11movemove-semanticsmove-constructor

Empty user-defined move constructor


The following code snippet which I was writing to understand move CTOR behaviour is giving me hard time to understand it's output:

#include <iostream>

class Temp
{
  public:

    Temp(){
      std::cout << "Temp DEFAULT CTOR called" << std::endl;
      mp_Val = nullptr;
    }

    Temp(int inp) { 
      std::cout << "Temp CTOR called" << std::endl;
      mp_Val = new int(inp); 
    }

    Temp(const Temp& inp) {
      std::cout << "Temp COPY CTOR called" << std::endl;
      mp_Val = new int(*inp.mp_Val); 
    }

    Temp& operator= (const Temp& inp) {
      std::cout << "Temp ASSIGNMENT OPER called" << std::endl;
      mp_Val = new int(*inp.mp_Val);

      return *this;
    }

    int* mp_Val;
};

class B
{
  public:

    B(){
      std::cout << "Class B DEFAULT CTOR" << std::endl; 
      mp_Val = nullptr;
    }
    B(int inp) { 
      std::cout << "Class B CTOR" << std::endl; 
      mp_Val = new Temp(inp);
    }

    B(const B& in) { 
      std::cout << "Class B COPY CTOR" << std::endl; 
      mp_Val = in.mp_Val;
    }

     B(B&& in){ 
      std::cout << "Class B MOVE CTOR" << std::endl; //Doubt: 1
    }

    Temp *mp_Val;
};

int main() {
  B obj1(200);
  B obj2 = std::move(obj1);
  auto temp = obj1.mp_Val;
  std::cout << "Obj1 B::Temp address: " << obj1.mp_Val << std::endl;

  std::cout << "Obj2 B::Temp address: " << obj2.mp_Val << std::endl; //Doubt: 2

  return 0;
}

Output:

Class B CTOR
Temp CTOR called
Class B MOVE CTOR
Obj1 B::Temp address: 0xd48030
Obj2 B::Temp address: 0x400880

GCC version: 4.6.3

My question is about the line marked as Doubt 2. Should not the address be printed as 0? As per my understanding, as I have defined an empty move CTOR (marked as Doubt 1) in class B, it should call the default CTOR of class Temp (which it's not calling as evident from the logs) to initialise its member variable mp_Val of type Temp.

There is obviously something that I am missing.


Solution

  • As per my understanding, as I have defined an empty move CTOR (marked as Doubt 1) in class B, it should call the default CTOR of class Temp (which it's not calling as evident from the logs) to initialise its member variable mp_Val of type Temp.

    Your member variable isn't of type Temp, it's of type Temp *. You're right that the lack of an initialiser means that that member will be default-constructed, and for type Temp that would involve calling the default constructor. However, for pointer types, default construction leaves the object uninitialised.