Discussion
A swap function typically looks like this, where U is some user-defined type:class T {// …
public:
void swap( T& rhs ) {
member1_.swap( rhs.member1_ );
std::swap( member2_, rhs.member2_ );
}
private:
U member1_;
int member2_;
};
For primitive types and for standard containers, std::swap will do. Other classes might implement swapping as a member function under various names.Consider using swap to implement copy assignment in terms of copy construction. The following implementation of operator= provides the strong guarantee (see Item 71), although at the price of creating an extra object, which can be inappropriate if there are more efficient ways to perform error-safe assignment for T objects:T& T::operator=( const T& other ) { // good: Variant #1 (traditional)
T temp( other );
swap( temp );
return *this;
}
T& T::operator=( T temp ) { // good: Variant #2 (see Item 27)
swap( temp ); // note: temp passed by value
return *this;
}
What if U does not implement a no-fail swap function, as is the case with many legacy classes, and you still need T to support a swap function? All is not lost:Item 43.)
Never use the trick of implementing copy assignment in terms of copy construction by using an explicit destructor followed by placement new , even though this trick still crops up regularly in C++ forums. (See also Item 99.) That is, never write:T& T::operator=( const T& rhs ) { // bad: an anti-idiom
if( this != &rhs ) {
this->~T(); // this technique is evil
new (this) T( rhs ); // (see [Sutter00] §41)
}
return *this;
}
Prefer to provide a nonmember swap function in the same namespace as your type when objects of your type have a way to exchange their values more efficiently than via brute-force assignment, such as if they have their own swap or equivalent function (see Item 57). Additionally, consider specializing std::swap for your own nontemplate types:namespace std {
template<> void swap( MyType & lhs, MyType & rhs) { // for MyType objects,
lhs.swap ( rhs ); // use MyType::swap
}
}
The standard does not allow you to do this when MyType is itself a template class. Fortunately, this specialization is just a nice-to-have; the primary technique is to provide a type-customized swap as a nonmember in the same namespace as the type.