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

Keine Kommentare:

Kommentar veröffentlichen