Я обращаюсь к этому вопросу: Что такое идиома копирования и свопинга?
Эффективно, приведенный выше ответ приводит к следующей реализации:
class MyClass
{
public:
friend void swap(MyClass & lhs, MyClass & rhs) noexcept;
MyClass() { /* to implement */ };
virtual ~MyClass() { /* to implement */ };
MyClass(const MyClass & rhs) { /* to implement */ }
MyClass(MyClass && rhs) : MyClass() { swap(*this, rhs); }
MyClass & operator=(MyClass rhs) { swap(*this, rhs); return *this; }
};
void swap( MyClass & lhs, MyClass & rhs )
{
using std::swap;
/* to implement */
//swap(rhs.x, lhs.x);
}
Однако обратите внимание, что мы могли бы вообще отказаться от swap(), выполнив следующее:
class MyClass
{
public:
MyClass() { /* to implement */ };
virtual ~MyClass() { /* to implement */ };
MyClass(const MyClass & rhs) { /* to implement */ }
MyClass(MyClass && rhs) : MyClass() { *this = std::forward<MyClass>(rhs); }
MyClass & operator=(MyClass rhs)
{
/* put swap code here */
using std::swap;
/* to implement */
//swap(rhs.x, lhs.x);
// :::
return *this;
}
};
Обратите внимание, что это означает, что мы больше не будем иметь действительный зависимый от аргумента поиск в std:: swap с MyClass.
Короче, есть ли преимущество использования метода swap().
изменить:
Я понял, что во второй реализации выше есть ужасная ошибка, и ее довольно большая вещь, поэтому я оставлю ее как есть, чтобы наставлять всех, кто сталкивается с этим.
если оператор = определяется как
MyClass2 & operator=(MyClass2 rhs)
Тогда, когда rhs является r-значением, будет вызываться конструктор перемещения. Однако это означает, что при использовании:
MyClass2(MyClass2 && rhs)
{
//*this = std::move(rhs);
}
Обратите внимание, что в итоге вы получаете рекурсивный вызов конструктору перемещения, поскольку operator = вызывает конструктор перемещения...
Это очень тонко и трудно обнаружить до тех пор, пока вы не получите переполнение стека во время выполнения.
Теперь исправление будет состоять в том, чтобы иметь как
MyClass2 & operator=(const MyClass2 &rhs)
MyClass2 & operator=(MyClass2 && rhs)
это позволяет нам определить конструкторы копирования как
MyClass2(const MyClass2 & rhs)
{
operator=( rhs );
}
MyClass2(MyClass2 && rhs)
{
operator=( std::move(rhs) );
}
Обратите внимание, что вы пишете одинаковый объем кода, конструкторы копирования становятся "свободными", и вы просто пишете operator = (&) вместо конструктора копирования и оператора = (& &) вместо свопа().