c+ - Qu'est-ce que l'idiome de copie et de swap

Mots clés : c++copy-constructorassignment-operatorc++-faqcopy-and-swapc++

meilleur 5 Réponses c+ - Qu'est-ce que l'idiome de copie et de swap

vote vote

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) 
vote vote

83

T& operator=(T tmp) {     this->swap(tmp);     return *this; } 
vote vote

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_))     { } }; 
vote vote

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);  } 
vote vote

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); } 

Questions similaires