zoukankan      html  css  js  c++  java
  • [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.  
  • 相关阅读:
    面向对象课程设计-FlappyCharacter(个人)
    学生成绩管理系统——个人博客
    学生成绩管理系统(个人)
    JAVA课程设计个人博客----FlappyBird
    Java课程设计——彩票购买抽奖系统
    彩票抽奖程序—个人博客
    彩票购买抽奖程序——个人博客
    面对对象综合设计-贪吃蛇个人博客
    面向对象综合设计-贪吃蛇
    面向对象程序综合设计—课程设计
  • 原文地址:https://www.cnblogs.com/hustcser/p/4184481.html
Copyright © 2011-2022 走看看