#include <iostream>
#include <string>
/*
When it comes to move assignment, we cannot just use std::swap(*this, rhs);
It is because std::swap combines with three std::move commands: one is a move
constructor, the other two are move assignments. So it will result in endless
recursion from call move assignment within move assignment.
*/
using std::cin; using std::cout; using std::endl;
class MetaData
{
public:
MetaData (int size, const std::string& name)
: _name( name )
, _size( size )
{
cout << "MetaData initialiser!" << endl;
}
// copy constructor
MetaData (const MetaData& other)
: _name( other._name )
, _size( other._size )
{
cout << "MetaData copy constructor!" << endl;
}
// move constructor
MetaData (MetaData&& other)
: _name( std::move(other._name) )
, _size( other._size )
{
cout << "MetaData move constructor!" << endl;
}
MetaData &operator= (MetaData &other)
{
if(this != &other)
{
_name = other._name;
_size = other._size;
}
cout << "MetaData copy assignment!" << endl;
return *this;
}
MetaData &operator= (MetaData &&other)
{
if(this != &other)
{
_name = other._name;
_size = other._size;
other._name = "";
other._size = 0;
}
cout << "MetaData move assignment!" << endl;
return *this;
}
std::string getName () const { return _name; }
int getSize () const { return _size; }
private:
std::string _name;
int _size;
};
class ArrayWrapper
{
public:
// default constructor produces a moderately sized array
ArrayWrapper ()
: _p_vals( new int[ 64 ] )
, _metadata( 64, "ArrayWrapper" )
{}
ArrayWrapper (int n)
: _p_vals( new int[ n ] )
, _metadata( n, "ArrayWrapper" )
{}
// move constructor
ArrayWrapper (ArrayWrapper&& other)
: _p_vals( other._p_vals )
, _metadata( std::move(other._metadata) )
{
cout << "ArrayWrapper move constructor!" << endl;
other._p_vals = NULL;
}
// copy constructor
ArrayWrapper (const ArrayWrapper& other)
: _p_vals( new int[ other._metadata.getSize() ] )
, _metadata( other._metadata )
{
for ( int i = 0; i < _metadata.getSize(); ++i )
{
_p_vals[ i ] = other._p_vals[ i ];
}
}
~ArrayWrapper ()
{
delete [] _p_vals;
}
private:
int *_p_vals;
MetaData _metadata;
};
class Integer
{
public:
Integer(int n, std::string s):elem(n),str(s)
{
cout << "Integer initialiser!" << endl;
}
Integer(const Integer &val):elem(val.elem)
{
str = "COPY";
cout << "Integer copy constructor!" << endl;
}
Integer(Integer &&val):elem(val.elem)
{
str = "MOVE";
cout << "Integer move constructor!" << endl;
}
Integer &operator=(const Integer &val)
{
cout << "****** Integer copy assignment begins! ******" << endl;
// if(this != &val)
// {
// elem = val.elem;
// str = val.str;
// cout << "Integer copy assignment!" << endl;
// }
Integer copy = val;
std::swap(*this, copy);
cout << "********* Integer copy assignment ends *******" << endl;
return *this;
}
Integer &operator=(Integer &&val)
{
cout << "******* Integer move assignment begins! *******" << endl;
std::swap(elem, val.elem);
std::swap(str, val.str);
cout << "******* Integer move assignment ends! *******" << endl;
return *this;
}
std::string getVal()
{
return str;
}
private:
int elem;
std::string str;
};
Integer ret()
{
Integer tmp(100, "tmp");
return tmp;
}
int main()
{
// ArrayWrapper aw1;
// ArrayWrapper aw3(aw1);
Integer i1(99,"i1");
Integer i2(100,"i2");
// cout << i2.getVal() << endl;
i2 = {1, "haha"};
cout << endl;
i2= i1;
cout << i2.getVal() << endl;
return 0;
}