C++.Coding.Standards.1918.Rules.Guidelines [Electronic resources]

Herb Sutter, Andrei Alexandrescu

نسخه متنی -صفحه : 521/ 295
نمايش فراداده

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.