/* RULE OF THREE if you define a custome destructor, copy constructor or copy = operator, then you should define all three, and define them consistently. Rule of Five: both custom copy and move semantics, define all five. Ruel of Zero: Use smart pointers, leave to defaults. Separate copying from cloning. */ #include #include #include #include using namespace std; template // a structure implementing the rule of five struct myvector { private: T* ptr; unsigned int length{0}; unsigned int capacity; public: myvector(unsigned int cap) { ptr = new T[cap]; capacity = cap; } myvector(std::initializer_list m) { ptr = new T[m.size()]; capacity = m.size(); for(auto x:m) ptr[length++] = x; } T& operator [](unsigned int i) { return ptr[i]; } ~myvector() { if (ptr) delete[] ptr; } void resize() { // double capacity T* ptr2 = new T[capacity*2]; capacity *= 2; for(int i=0;i= capacity) resize(); ptr[length++] = x; } T pop_back() { return ptr[--length]; } // copy constructor myvector(const myvector& other) { capacity = other.capacity; length = other.length; ptr = new T[capacity]; for(int i=0;i& operator =(const myvector& other) { capacity = other.capacity; length = other.length; if (ptr) delete[] ptr; ptr = new T[capacity]; for(int i=0;i&& other) { // move constructor capacity = other.capacity; length = other.length; ptr = other.ptr; other.ptr = nullptr; other.capacity = 0; other.length = 0; } void operator =(myvector&& other) { capacity = other.capacity; length = other.length; if (ptr) delete[] ptr; // unique_ptr ptr = other.ptr; other.ptr = nullptr; // transfer of ownership other.capacity = 0; other.length = 0; } }; // Modern version, using the RULE OF ZERO template struct vec { private: unique_ptr ptr; unsigned int length{0}; unsigned int capacity; public: vec(unsigned int cap) { ptr = make_unique(cap); capacity = cap; } vec(std::initializer_list m) { ptr = make_unique(m.size()); capacity = m.size(); for(auto x:m) ptr[length++] = x; } void resize() { capacity *= 2; unique_ptr ptr2 = make_unique(capacity); for(int i=0;i=capacity) resize(); ptr[length++] = move(x); } T pop_back() { return ptr[--length]; } // separate cloning from copying. vec clone() { vec theclone(capacity); theclone.length = length; for(int i=0;i v{3,4,5,6}; myvector w{1,2,3,4,5}; cout << v[1] << endl; v.push_back(99); v[2] = 88; cout << v[4] << endl; myvector z = w; // call move constructor v = move(w); // call move = operator cout << v[0] << endl; //cout << w[0] << endl; unique_ptr a = make_unique(5); // int* a = new int(5); unique_ptr b = make_unique(5); // int *b = new int[5]; unique_ptr c = make_unique(6); c = move(a); // if c is pointing to something, delete it // c = a // a = nullptr; // don't mix raw pointers with unique pointers: //memcpy(&a,&c,sizeof(unique_ptr)); int x = 2; int y = 3; x = move(y); // x=y cout << *c << endl; //cout << *a << endl; vec p{3,4,5,6}; vec q{1,23,4,5,7}; p = move(q); return 0; }//main