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

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

 template <class T> void swap ( T& a, T& b )
{
T c(a);
a=b;
b=c;
}

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

2.针对int型优化:

 void swap(int & __restrict a, int & __restrict b)
{
  a ^= b;
  b ^= a;
  a ^= b;
}

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

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

 template <typename T> void Swap(T & obj1,T & obj2)
{
unsigned char * pObj1 = reinterpret_cast<unsigned char *>(&obj1);
unsigned char * pObj2 = reinterpret_cast<unsigned char *>(&obj2);
for (unsigned long x = ; x < sizeof(T); ++x)
{
pObj1[x] ^= pObj2[x];
pObj2[x] ^= pObj1[x];
pObj1[x] ^= pObj2[x];
}
}

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

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

 template <class T> void swap ( T& a, T& b )
{
a = a + b;
b = a - b;
a = a - b;
}

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

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

string:

 template<class _Ty,
class _Alloc> inline
void swap(vector<_Ty, _Alloc>& _Left, vector<_Ty, _Alloc>& _Right)
{ // swap _Left and _Right vectors
_Left.swap(_Right);
}
void swap(_Myt& _Right)
{ // exchange contents with _Right
if (this == &_Right)
; // same object, do nothing
else if (this->_Alval == _Right._Alval)
{ // same allocator, swap control information
#if _HAS_ITERATOR_DEBUGGING
this->_Swap_all(_Right);
#endif /* _HAS_ITERATOR_DEBUGGING */
this->_Swap_aux(_Right);
_STD swap(_Myfirst, _Right._Myfirst);
_STD swap(_Mylast, _Right._Mylast);
_STD swap(_Myend, _Right._Myend);
}
else
{ // different allocator, do multiple assigns
this->_Swap_aux(_Right);
_Myt _Ts = *this;
*this = _Right;
_Right = _Ts;
}
}

vector:

 template<class _Elem,
class _Traits,
class _Alloc> inline
void __CLRCALL_OR_CDECL swap(basic_string<_Elem, _Traits, _Alloc>& _Left,
basic_string<_Elem, _Traits, _Alloc>& _Right)
{ // swap _Left and _Right strings
_Left.swap(_Right);
}
void __CLR_OR_THIS_CALL swap(_Myt& _Right)
{ // exchange contents with _Right
if (this == &_Right)
; // same object, do nothing
else if (_Mybase::_Alval == _Right._Alval)
{ // same allocator, swap control information
#if _HAS_ITERATOR_DEBUGGING
this->_Swap_all(_Right);
#endif /* _HAS_ITERATOR_DEBUGGING */
_Bxty _Tbx = _Bx;
_Bx = _Right._Bx, _Right._Bx = _Tbx;
size_type _Tlen = _Mysize;
_Mysize = _Right._Mysize, _Right._Mysize = _Tlen;
size_type _Tres = _Myres;
_Myres = _Right._Myres, _Right._Myres = _Tres;
}
else
{ // different allocator, do multiple assigns
_Myt _Tmp = *this;
*this = _Right;
_Right = _Tmp;
}
}

第二个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函数。

 shared_ptr & operator=( shared_ptr const & r ) // never throws
{
this_type(r).swap(*this);
return *this;
}
void swap(shared_ptr<T> & other) // never throws
{
std::swap(px, other.px);
pn.swap(other.pn);
}

String::opreator=函数的优化:

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

 String& String::operator =(const String & rhs)
{
if (itsString)
delete [] itsString;
itsLen = rhs.GetLen();
itsString = new char[itsLen+];
for (unsigned short i = ;i<itsLen;i++)
itsString[i] = rhs[i];
itsString[itsLen] = '/0';
return *this;
}

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

 String& String::operator =(const String & rhs)
{
if (this == &rhs)
return *this;
if (itsString)
delete [] itsString;
itsLen=rhs.GetLen();
itsString = new char[itsLen+];
for (unsigned short i = ;i<itsLen;i++)
itsString[i] = rhs[i];
itsString[itsLen] = '/0';
return *this;
}

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

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

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

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

[020]转--C++ swap函数的更多相关文章

  1. 关于swap函数传值的问题

    #include <stdio.h> void swap(int * p3,int * p4); int main() {  int a = 9;  int b = 8;  int * p ...

  2. 自己写一个swap函数交换任意两个相同类型元素的值 对空指针的使用 字节大小的判断(二)了解原理

    验证的代码: #include <stdio.h> int main(){ char c = 'z'; ) + (c << ) + () + 'a'; printf(" ...

  3. swap函数的四种写法

    swap 函数的四种写法 (1)经典型 --- 嫁衣法 void swap(int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp; } ( ...

  4. c++ swap 函数

    转载地址 1,最通用的模板交换函数模式:创建临时对象,调用对象的赋值操作符. template <class T> void swap ( T& a, T& b ) { T ...

  5. [转]谈谈C++中的swap函数

    1,最通用的模板交换函数模式:创建临时对象,调用对象的赋值操作符. template <class T> void swap ( T& a, T& b ) { T c(a) ...

  6. [Effective C++ --025]考虑写出一个不抛异常的swap函数

    引言 在我的上一篇博客中,讲述了swap函数. 原本swap只是STL的一部分,而后成为异常安全性编程的脊柱,以及用来处理自我赋值可能性. 一.swap函数 标准库的swap函数如下: namespa ...

  7. 从Swap函数谈加法溢出问题

    1.      初始题目 面试题:). 这个题目太经典,也太简单,有很多人都会不假思索结出答案: //Code 1 void Swap(int* a, int* b) { *a = *a + *b; ...

  8. EC读书笔记系列之13:条款25 考虑写出一个不抛异常的swap函数

    记住: ★当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定其不抛出异常 ★若你提供一个member swap,也该提供一个non-member swap来调用前者.对于cla ...

  9. 【转】 谈谈C++中的swap函数

    1,最通用的模板交换函数模式:创建临时对象,调用对象的赋值操作符. template <class T> void swap ( T& a, T& b ) { T c(a) ...

随机推荐

  1. ♫【jQuery插件】图片放大镜

    JQZoom

  2. 服务器上的iptables

    服务器上的iptables 防火墙设置脚本规则 完整脚本如下: 复制代码代码示例: #!/bin/bash# by www.jbxue.comiptab="/sbin/iptables&qu ...

  3. POJ 1017 Packets

    题意:有一些1×1, 2×2, 3×3, 4×4, 5×5, 6×6的货物,每个货物高度为h,把货物打包,每个包裹里可以装6×6×h,问最少几个包裹. 解法:6×6的直接放进去,5×5的空隙可以用1× ...

  4. HttpListener supports SSL only for localhost? install certificate

    1.Start-All Programs - 2.execute below lines on that ‘Developer Command Prompt..’ tool makecert -n & ...

  5. 《转》高级Unix命令

    原文链接:http://coolshell.cn/articles/1044.html 在Unix操作中有太多太多的命令,这些命令的强大之处就是一个命令只干一件事,并把这件事干好.Do one thi ...

  6. ios游戏开发--cocos2d学习(3)

    ------------继续上一节的内容. “接收触摸事件”: CCLayer类是用来接收触摸输入的.不过你要首先启用这个功能才可以使用它. self.isTouchEnabled = YES;//此 ...

  7. 使用C语言实现二维,三维绘图算法(3)-简单的二维分形

    使用C语言实现二维,三维绘图算法(3)-简单的二维分形 ---- 引言---- 每次使用OpenGL或DirectX写三维程序的时候, 都有一种隔靴搔痒的感觉, 对于内部的三维算法的实现不甚了解. 其 ...

  8. Python第一个入门程序

    #!usr/bin/env python3 #在UNIX上,当某程序在控制台中被引用时,该文件的头两个字节先被读入.如果这两个字节是ASCII字符 #!, #shell就会认为该文件将要由解释器执行, ...

  9. Android 网络权限配置

    Android开发应用程序时,如果应用程序需要访问网络权限,需要在 AndroidManifest.xml 中加入以下代码 <uses-permission android:name=”andr ...

  10. 本地已有SVN项目导入到eclipse中

    有时候在本地上checkout了项目,在eclipse中不希望重新checkout一次,可以如下操作: 1.在project上右键-> team -> share project -> ...