Mots clés : c++copy-constructorassignment-operatorc++-faqcopy-and-swapc++
94
#include <algorithm> // std::copy #include <cstddef> // std::size_t class dumb_array { public: // (default) constructor dumb_array(std::size_t size = 0) : mSize(size), mArray(mSize ? new int[mSize]() : nullptr) { } // copy-constructor dumb_array(const dumb_array& other) : mSize(other.mSize), mArray(mSize ? new int[mSize] : nullptr) { // note that this is non-throwing, because of the data // types being used; more attention to detail with regards // to exceptions must be given in a more general case, however std::copy(other.mArray, other.mArray + mSize, mArray); } // destructor ~dumb_array() { delete [] mArray; } private: std::size_t mSize; int* mArray; };
// the hard part dumb_array& operator=(const dumb_array& other) { if (this != &other) // (1) { // get rid of the old data... delete [] mArray; // (2) mArray = nullptr; // (2) *(see footnote for rationale) // ...and put in the new mSize = other.mSize; // (3) mArray = mSize ? new int[mSize] : nullptr; // (3) std::copy(other.mArray, other.mArray + mSize, mArray); // (3) } return *this; }
dumb_array& operator=(const dumb_array& other) { if (this != &other) // (1) { // get the new data ready before we replace the old std::size_t newSize = other.mSize; int* newArray = newSize ? new int[newSize]() : nullptr; // (3) std::copy(other.mArray, other.mArray + newSize, newArray); // (3) // replace the old data (all are non-throwing) delete [] mArray; mSize = newSize; mArray = newArray; } return *this; }
class dumb_array { public: // ... friend void swap(dumb_array& first, dumb_array& second) // nothrow { // enable ADL (not necessary in our case, but good practice) using std::swap; // by swapping the members of two objects, // the two objects are effectively swapped swap(first.mSize, second.mSize); swap(first.mArray, second.mArray); } // ... };
dumb_array& operator=(dumb_array other) // (1) { swap(*this, other); // (2) return *this; }
dumb_array& operator=(const dumb_array& other) { dumb_array temp(other); swap(*this, temp); return *this; }
class dumb_array { public: // ... // move constructor dumb_array(dumb_array&& other) noexcept †† : dumb_array() // initialize via default constructor, C++11 only { swap(*this, other); } // ... };
dumb_array& operator=(dumb_array other); // (1)
83
T& operator=(T tmp) { this->swap(tmp); return *this; }
80
X& operator=(X rhs) { swap(rhs); return *this; }
struct X { T* p_; size_t size_; X& operator=(const X& rhs) { delete[] p_; // OUCH! p_ = new T[size_ = rhs.size_]; std::copy(p_, rhs.p_, rhs.p_ + rhs.size_); } ... };
struct Client { IP_Address ip_address_; int socket_; X(const X& rhs) : ip_address_(rhs.ip_address_), socket_(connect(rhs.ip_address_)) { } };
68
friend void swap(A& first, A& second) { std::swap(first.size, second.size); std::swap(first.arr, second.arr); }
void swap(A& other) { std::swap(size, other.size); std::swap(arr, other.arr); }
56
void fs(std::vector<T, A> & a, std::vector<T, A> & b) { a.swap(b); b.clear(); // not important what you do with b } void fm(std::vector<T, A> & a, std::vector<T, A> & b) { a = std::move(b); }