首页 > 代码库 > [020]转--C++ swap函数
[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.
[020]转--C++ swap函数