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.