vendredi 16 octobre 2020

C++: Move constructor not called, unless explicit casting is called [closed]

I created a class, "ListElement", that contains as a single data variable an instance of the class "MyClass" which contains a dynamically allocated array.

  • For ListElement I created a default constructor which delegates to a right-value constructor that initializes an instance of MyClass.

  • For MyClass I created a constructor which initializes its array to an inputted value (and a default constructor which delegates to the one above with value 0). Furthermore, I included a copy and a move constructor.

I'm, however, mostly confused, why the move constructor is not called unless the datatype is casted as an r-value reference explicitly, although it is already passed as such (see below).

#include <iostream>

template <int arrSize>
class MyClass {
private:
  // Data
  int* a;

public:
  //Constructor
  MyClass(int value){
    this->a = new int[arrSize];
    for(unsigned int i = 0; i<arrSize; ++i){
      a[i] = value;
    }
    std::cout << "MyClass created!" << std::endl;
  }
  MyClass(): MyClass(0){}
  //Copy  Constructor
  MyClass(const MyClass<arrSize>& other){
    this->a = new int[arrSize];
    for(unsigned int i = 0; i<arrSize;++i){
      a[i] = other.a[i];
    }
    std::cout << "MyClass copied!" << std:: endl;
  }
  //Move Constructor
  MyClass(MyClass<arrSize>&& other){
    this->a = other.a;
    other.a = nullptr;
    std::cout << "MyClass moved!" << std::endl;
  }
  //Destructor
  ~MyClass(){
    delete[] this->a;
    std::cout << "MyClass deleted!" << std::endl;
  }
};

class ListElement {
public:
  //Constructors
  ListElement(MyClass<5>&& data) : data((MyClass<5>&&)data) {} // QUESTION 
  ListElement(): ListElement(MyClass<5>(1)){}

private:
  //Data
  MyClass<5> data;
};

int main() {
  ListElement myZeroListElement{};
  return 0;
}

Question: Why is the copy constructor called if I write for this line (see comments)?

ListElement(MyClass<5>&& data) : data(data) {}

"data" is a right-value reference, but the move constructor is only called when I explecitly cast it, so-to-say, again into a right-value reference like this:

ListElement(MyClass<5>&& data) : data((MyClass<5>&&)data) {}

GREATLY APPRECIATED!

Aucun commentaire:

Enregistrer un commentaire