原文来自: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. java高并发,如何解决,什么方式解决

    之前我将高并发的解决方法误认为是线程或者是队列可以解决,因为高并发的时候是有很多用户在访问,导致出现系统数据不正确.丢失数据现象,所以想到 的是用队列解决,其实队列解决的方式也可以处理,比如我们在竞拍 ...

  2. Android 中的MVP 模式

    MVP模式的核心思想: MVP把Activity中的UI逻辑抽象成View接口,把业务逻辑抽象成功接口,Model类还是原来的Model. MVC 其中View层其实就是程序的UI界面,用于向用户展示 ...

  3. onAttachedToWindow () 和 onDetachedFromWindow () ; 以及更新视图的函数ondraw() 和dispatchdraw()的区别

    protected void onAttachedToWindow() This is called when the view is attached to a window. At this po ...

  4. 【Python】使用python的tornado配合html页面示例

    背景:java写的非标加密算法,测试时执行java工程进行解密测试,很不方便. 目的:想写个web页面,使得任何测试人员都可以在输入加密串时得到解密后字段,方便日志查询及字段核对.(额,算法部分就不写 ...

  5. Linux 多线程编程--线程退出

    今天分析项目中进程中虚存一直增长问题,运行10个小时虚存涨到121G ,RSS占用为16G 非常恐怖. Valgrind测试无内存泄漏. 内存32G 64bit系统信息如下: Linux线程使用方式是 ...

  6. DELL R710服务器可以安装的VMWare ESX Server 4.1 全套下载带注册码

    随着R710的停产,R720随之面世,但DELL R720服务器只支持vmware esxi5.0以上,DELL客户经理给了一套系统安装后序列号无法解决,还是用4.1好了,却又发现怎么都无法安装.按网 ...

  7. Hadoop安装教程_单机/伪分布式配置

    环境 本教程使用 CentOS 6.4 32位 作为系统环境,请自行安装系统(可参考使用VirtualBox安装CentOS).如果用的是 Ubuntu 系统,请查看相应的 Ubuntu安装Hadoo ...

  8. V&View更新

    这几天一直在做V&View的更新工作,这次的更新是质的变化,表面界面变化不大,可是内部确有着翻天覆地的改变. 这几天我主要做了一下几件事: 1. 重新构思了vview的文章发布形式,之前使用k ...

  9. prefuse学习(二)显示一张图

    1.  把数据以点连线的方式在画面中显示 2.  数据按照数据的性别属性使用不同的颜色 3.  鼠标左键可以把图在画面中拖动 4.  鼠标右键可以把图放大或者缩小 5.  鼠标单击某个数据上,该数据点 ...

  10. 关于图像读取函数imread()的一点使用经验,注意默认参数的赋值

    读入数字图像到数组,用CNN进行训练,发现关于图像读取的一个问题. 问题描述:读取灰度数字图像,在验证时发现存在错误,从图像到数组中的值不完全一样? main code as follows: int ...