Copy and Swap技巧小记

读Effective C++ 条款11在处理operator= “自我赋值的时候” 不仅要考虑是否自我赋值,还讨论了新赋值的内存分配时候的异常安全性。

用到了一种叫做copy and swap的技巧,不过我觉得应该叫做temp and swap,因为主要是将内存分配的问题交给了本类的temp,通过swap的方式偷梁换柱了temp的数据成员,即使函数完成,temp被销毁,销毁的数据也是swap之后不要的那份。

我觉得这个技巧真的很巧妙。

最好的例子:

一个Mystring类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class MyString
{
public:
MyString(void);
MyString(const char* pData);
MyString(const MyString& str);
MyString& operator=(const MyString& str); //令赋值操作符返回一个reference to *this,可以实现连锁赋值操作,STL中都是这样做的,Effective也是这么推荐的。
~MyString(void);
private:
char* m_pData;
};
MyString::MyString(void)
{
this->m_pData = new char[1];
if ( m_pData == NULL)
{
std::cerr<<"存储空间分配错误!\n";
exit(1); //exit(0):正常运行程序并退出程序;exit(1):非正常运行导致退出程序;return(): 返回函数,若在主函数中,则会退出函数并返回一值。
}
m_pData[0] = '\0';
}
MyString::MyString(const char* pData)
{
this->m_pData = new char[strlen(pData)+1];
if ( m_pData == NULL)
{
std::cerr<<"存储空间分配错误!\n";
exit(1);
}
strcpy(this->m_pData, pData);
//不必为最后一个字符赋零值因为ctrcpy中已经实现
}
MyString::MyString(const MyString& str)
{
this->m_pData = new char[strlen(str.m_pData)+1];
if ( m_pData == NULL)
{
std::cerr<<"存储空间分配错误!\n";
exit(1);
}
strcpy(this->m_pData, str.m_pData);
}
MyString& MyString::operator=(const MyString& str)
{
if (this != &str) //防止自我赋值
{
MyString temp(str); //copy and swap,增加异常安全性,保证内存分配成功再进行赋值交换(E-cP56)
char* pTemp = temp.m_pData;
temp.m_pData = this->m_pData;
this->m_pData = pTemp; //这三句巧妙在将临时对象temp中的m_pData换掉了,即使函数结束,temp中的m_pData被释放掉,释放掉的也是换掉之后的了。
}
return *this; //如果是自我赋值则返回自己即可
}
MyString::~MyString(void)
{
delete[] m_pData;
}

本文标题:Copy and Swap技巧小记

文章作者:Yang Shuai

发布时间:2018年06月24日 - 20:06

最后更新:2018年06月24日 - 20:06

原始链接:https://ysbbswork.github.io/2018/06/24/Copy-and-Swap技巧小记/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

坚持原创技术分享,您的支持将鼓励我继续创作!