[020]转--C++ swap函数

原文来自:http://www.cnblogs.com/xloogson/p/3360847.html

1.C++最通用的模板交换函数模式:创建临时对象,调用对象的赋值操作符

1 template <class T> void swap ( T& a, T& b )  
2 {  
3     T c(a); 
4     a=b; 
5     b=c;  
6 }  

需要构建临时对象,一个拷贝构造,两次赋值操作。

 2.针对int型优化:

1 void swap(int & __restrict a, int & __restrict b)  
2 {  
3   a ^= b;  
4   b ^= a;  
5   a ^= b;  
6 } 

无需构造临时对象,异或。

因为指针是int,所以基于这个思路可以优化1:

 1 template <typename T> void Swap(T & obj1,T & obj2)  
 2 {  
 3     unsigned char * pObj1 = reinterpret_cast<unsigned char *>(&obj1);  
 4     unsigned char * pObj2 = reinterpret_cast<unsigned char *>(&obj2);  
 5     for (unsigned long x = 0; x < sizeof(T); ++x)  
 6     {  
 7         pObj1[x] ^= pObj2[x];  
 8         pObj2[x] ^= pObj1[x];  
 9         pObj1[x] ^= pObj2[x];  
10     }  
11 }

可以省下拷贝构造的过程。

3.针对内建类型的优化:  int, float, double 等,甚至重载运算符的用户自定义类型:向量,矩阵,图像等。。。

1 template <class T> void swap ( T& a, T& b )
2 {
3     a = a + b;
4     b = a - b;
5     a = a - b;  
6 }

// 无需构造临时变量。使用基本运算操作符。

4.swap的一些特化:std::string, std::vector各自实现了swap函数

string:

 1 template<class _Ty,  
 2     class _Alloc> inline  
 3     void swap(vector<_Ty, _Alloc>& _Left, vector<_Ty, _Alloc>& _Right)  
 4     {   // swap _Left and _Right vectors  
 5     _Left.swap(_Right);  
 6     }  
 7     void swap(_Myt& _Right)  
 8         {   // exchange contents with _Right  
 9         if (this == &_Right)  
10             ;   // same object, do nothing  
11         else if (this->_Alval == _Right._Alval)  
12             {   // same allocator, swap control information  
13  #if _HAS_ITERATOR_DEBUGGING  
14             this->_Swap_all(_Right);  
15  #endif /* _HAS_ITERATOR_DEBUGGING */  
16             this->_Swap_aux(_Right);  
17             _STD swap(_Myfirst, _Right._Myfirst);  
18             _STD swap(_Mylast, _Right._Mylast);  
19             _STD swap(_Myend, _Right._Myend);  
20             }  
21         else  
22             {   // different allocator, do multiple assigns  
23             this->_Swap_aux(_Right);  
24             _Myt _Ts = *this;  
25             *this = _Right;  
26             _Right = _Ts;  
27             }  
28         }  

vector:

 1 template<class _Elem,  
 2     class _Traits,  
 3     class _Alloc> inline  
 4     void __CLRCALL_OR_CDECL swap(basic_string<_Elem, _Traits, _Alloc>& _Left,  
 5         basic_string<_Elem, _Traits, _Alloc>& _Right)  
 6     {   // swap _Left and _Right strings  
 7     _Left.swap(_Right);  
 8     }  
 9     void __CLR_OR_THIS_CALL swap(_Myt& _Right)  
10         {   // exchange contents with _Right  
11         if (this == &_Right)  
12             ;   // same object, do nothing  
13         else if (_Mybase::_Alval == _Right._Alval)  
14             {   // same allocator, swap control information  
15  #if _HAS_ITERATOR_DEBUGGING  
16             this->_Swap_all(_Right);  
17  #endif /* _HAS_ITERATOR_DEBUGGING */  
18             _Bxty _Tbx = _Bx;  
19             _Bx = _Right._Bx, _Right._Bx = _Tbx;  
20             size_type _Tlen = _Mysize;  
21             _Mysize = _Right._Mysize, _Right._Mysize = _Tlen;  
22             size_type _Tres = _Myres;  
23             _Myres = _Right._Myres, _Right._Myres = _Tres;  
24             }  
25         else  
26             {   // different allocator, do multiple assigns  
27             _Myt _Tmp = *this;  
28             *this = _Right;  
29             _Right = _Tmp;  
30             }  
31         }  

第二个swap(Right)进行判断,如果使用了相同的分配器,则直接交换控制信息,否则调用string::operator=进行拷贝赋值。。。所以建议优先使用swap函数,而不是赋值操作符。

5.Copy and  Swap idiom

目的:C++异常有三个级别:基本,强,没有异常。通过创建临时对象然后交换,能够实现重载赋值操作符的强异常安全的执行。

Loki中智能指针 临时变量跟this交换,临时变量自动销毁~

1 SmartPtr& operator=(SmartPtr<T1, OP1, CP1, KP1, SP1, CNP1 >& rhs)  
2 {  
3     SmartPtr temp(rhs);  
4     temp.Swap(*this);  
5     return *this;  
6 }  

boost::share_ptr,share_ptr定义了自己的swap函数。

 1 shared_ptr & operator=( shared_ptr const & r ) // never throws  
 2 {  
 3     this_type(r).swap(*this);  
 4     return *this;  
 5 }  
 6 void swap(shared_ptr<T> & other) // never throws  
 7 {  
 8     std::swap(px, other.px);  
 9     pn.swap(other.pn);  
10 }  

String::opreator=函数的优化:

最一般的写法,特点:使用const string& 传参防止临时对象。

 1 String& String::operator =(const String & rhs)  
 2 {  
 3     if (itsString)  
 4         delete [] itsString;  
 5     itsLen = rhs.GetLen();  
 6     itsString = new char[itsLen+1];  
 7     for (unsigned short i = 0;i<itsLen;i++)  
 8         itsString[i] = rhs[i];  
 9     itsString[itsLen] = '/0';  
10     return *this;  
11 }  

优化1,防止自我间接赋值,a = b; c = b; a = c; 如果没有第一个if判断,当把c赋给a的时候,删除了a.itsString,后面的拷贝就会出错。注意是if(this==&rhs), 而不是if(*this==rhs) .

 1 String& String::operator =(const String & rhs)  
 2 {  
 3     if (this == &rhs)  
 4         return *this;  
 5     if (itsString)  
 6         delete [] itsString;  
 7     itsLen=rhs.GetLen();  
 8     itsString = new char[itsLen+1];  
 9     for (unsigned short i = 0;i<itsLen;i++)  
10         itsString[i] = rhs[i];  
11     itsString[itsLen] = '/0';  
12     return *this;  
13 }  

优化2,不进行拷贝赋值,只是交换控制信息,而且是强异常安全:

1 String & String::operator = (String const &rhs)  
2 {  
3     if (this != &rhs)  
4         String(rhs).swap (*this); // Copy-constructor and non-throwing swap  
5     // Old resources are released with the destruction of the temporary above  
6     return *this;  
7 }  

优化3,以最原始的传值方式传参,避免临时对象创建:

1 String & operator = (String s) // the pass-by-value parameter serves as a temporary  
2 {  
3    s.swap (*this); // Non-throwing swap  
4    return *this;  
5 }// Old resources released when destructor of s is called.  

 

posted @ 2014-12-25 13:51  依然冷月  阅读(496)  评论(0编辑  收藏  举报