Posts mit dem Label move assignment operator werden angezeigt. Alle Posts anzeigen
Posts mit dem Label move assignment operator werden angezeigt. Alle Posts anzeigen

Freitag, 25. August 2017

The following code snipped shows the cases in which the different constructors and assignment operators will be used by the compiler: 

#include <iostream>
#include <vector>

using namespace std;

template<typename T>
class MyClass
{
public:
  MyClass(vector<T> inputVector);
  MyClass(const MyClass<T> &other);
  MyClass(MyClass &&other) noexcept;
  MyClass &operator=(const MyClass &other);
  MyClass &operator=(MyClass &&other);

  virtual ~MyClass();

private:
  vector<T> mVector;
};

template<typename T>
MyClass<T>::MyClass(vector<T> inputVector)
  : mVector{inputVector}
{
  cout << "\tMyClass constructor" << endl;
}

template<typename T>
MyClass<T>::MyClass(const MyClass<T> &other)
  : mVector{other.mVector}
{
  cout << "\tMyClass copy constructor" << endl;
}

template<typename T>
MyClass<T>::MyClass(MyClass<T> &&other) noexcept
  : mVector{std::move(other.mVector)}
{
  cout << "\tMyClass move constructor" << endl;
}

template<typename T>
MyClass<T>& MyClass<T>::operator=(const MyClass<T> &other)
{
  cout << "\tMyClass assignment operator" << endl;
  this->mVector = other.mVector;
  return *this;
}

template<typename T>
MyClass<T> &MyClass<T>::operator=(MyClass<T> &&other)
{
  cout << "\tMyClass move assignment operator" << endl;
  this->mVector.operator=( std::move(other.mVector) );
  return *this;
}


template<typename T>
MyClass<T>::~MyClass()
{
  cout << "\tMyClass vector size: " << mVector.size() << endl;
}


MyClass<int> GetClass()
{
  MyClass<int> obj{ {1, 2} };
  return obj;
}

MyClass<int> GetClass2()
{
  return MyClass<int>{ {1, 2} };
}

int main()
{
  {
    cout << "Constructor" << endl;
    MyClass<int> myClass{ { 1, 2 } };
  }
  {
    cout << "Move constructor" << endl;
    MyClass<int> myClass{GetClass()};
  }
  {
    cout << "Assignment operator" << endl;
    MyClass<int> origObj{ { 1, 2 } };
    MyClass<int> myClass{ { 3, 4 } };
    myClass = origObj;
  }
  {
    cout << "Move assignment operator" << endl;
    MyClass<int> myClass{ {3, 4} };
    myClass = GetClass2();
  }

  // References are handled differently:
  // A reference is basically a pointer to an object.
  // The references have to be const because the objects returned by the
  // GetClass functions are rvalues and thus the references have to be
  // rvalues also.
  {
    cout << "Reference construction (direct initialization)" << endl;
    const MyClass<int> &myClass{GetClass()};
  }
  {
    cout << "Reference construction (assignment)" << endl;
    const MyClass<int> &myClass = GetClass();
  }

  return 0;
}



This should result to the following output by the compiler:
Constructor
        MyClass constructor
        MyClass vector size: 2
Move constructor
        MyClass constructor
        MyClass move constructor
        MyClass vector size: 0
        MyClass vector size: 2
Assignment operator
        MyClass constructor
        MyClass constructor
        MyClass assignment operator
        MyClass vector size: 2
        MyClass vector size: 2
Move assignment operator
        MyClass constructor
        MyClass constructor
        MyClass move assignment operator
        MyClass vector size: 0
        MyClass vector size: 2
Reference construction (direct initialization)
        MyClass constructor
        MyClass move constructor
        MyClass vector size: 0
        MyClass vector size: 2
Reference construction (assignment)
        MyClass constructor
        MyClass move constructor
        MyClass vector size: 0
        MyClass vector size: 2