C++复制构造函数及三法则
来源:互联网 发布:写攻略的软件 编辑:程序博客网 时间:2024/05/17 06:46
C++复制构造函数及三法则
写在前面
本节这个精辟的例子摘自《数据结构与算法-C++版》第3版 清华出版社一书。
这里对该书的例子进行了整理,以帮助理解拷贝构造函数及C++三大法则。
结果为什么是这样的呢?
首先看下面例子代码。
//复制构造函数引起的错误#include <iostream>#include <string.h>using namespace std;struct Node{char *name;int age;//构造函数Node(char *n="",int a=0){ name = strdup(n); age = a;}};int main(){ Node node1("Roger",20),node2(node1); strcpy(node2.name,"Wendy"); node2.age = 30; cout << node1.name<<" "<<node1.age <<" "<<node2.name<<" "<<node2.age<<endl;}
例子中使用的strdup函数请参考文章末尾的补充说明部分的介绍。
这个例子的运行结果是 Roger 20 Wendy 30 ,对吗?
真正的结果是: Wendy 20 Wendy 30
影响结果的是因为在执行node2(node1)时调用了合成的复制构造函数,这个构造函数,执行的行为是:逐个成员初始化,将新对象初始化为原对象的副本。因此,实际上执行该语句后,node2与node1的name指向同一块内存区域,因此在strcpy(node2.name,"Wendy")后,两者的内容相同,而int型则执行简单赋值没有出错。
解决办法: 增加赋值构造函数
//复制构造函数 Node(const Node& node){ name = strdup(node.name); age = node.age;}
结果为什么又是这样的呢?
再看下面的例子:
//赋值操作符引起的错误#include <iostream>#include <string.h>using namespace std;struct Node{char *name;int age;//构造函数Node(char *n="",int a=0){ name = strdup(n); age = a;} //复制构造函数 Node(const Node& node){ name = strdup(node.name); age = node.age; cout<<"copy constructor"<<endl;}};int main(){ Node node1("Roger",20),node2; node2 = node1; strcpy(node2.name,"Wendy"); node2.age = 30; cout << node1.name<<" "<<node1.age <<" "<<node2.name<<" "<<node2.age<<endl;}
这个例子的运行结果应该是 Roger 20 Wendy 30 了吧?
错了,真正的结果还是: Wendy 20 Wendy 30
解决办法: 增加赋值操作符重载函数
//重载赋值操作符Node& operator = (const Node& node){ if(this != &node){ if(name != NULL) delete[] name; name = strdup(node.name); age = node.age;}return *this;}
这样程序才能如期工作。但是还有一点需要注意,程序中使用strdup分配的内存并没有释放,因此还需要添加析构函数。
//析构函数~Node(){ if(name != NULL) delete[] name;}
完整的代码如下:
//如果一个类需要析构函数,则它也需要赋值操作符和复制构造函数(三法则)#include <iostream>#include <string.h>using namespace std;struct Node{char *name;int age;//构造函数Node(char *n="",int a=0){ name = strdup(n); age = a;} //复制构造函数 Node(const Node& node){ name = strdup(node.name); age = node.age;}//重载赋值操作符Node& operator = (const Node& node){ if(this != &node){ if(name != NULL) delete[] name; name = strdup(node.name); age = node.age;}return *this;}//析构函数~Node(){ if(name != NULL) delete[] name;}};int main(){ Node node1("Roger",20),node2(node1); strcpy(node2.name,"Wendy"); node2.age = 30; cout << node1.name<<" "<<node1.age <<" "<<node2.name<<" "<<node2.age<<endl;}
这里我们要强调的三法则,即是如果一个类需要析构函数,则它也需要赋值操作符和复制构造函数。
在c++ 11中三法则演变成了五法则,具体可以参考:Rule of three (C++ programming)
补充说明:
函数strdup
头文件:#include <string.h>
定义函数:char * strdup(const char *s);
函数说明:strdup()会先用maolloc()配置与参数s 字符串相同的空间大小,然后将参数s 字符串的内容复制到该内存地址,然后把该地址返回。该地址最后可以利用free()来释放。
返回值:返回一字符串指针,该指针指向复制后的新字符串地址。若返回NULL 表示内存不足。(摘自:C语言strdup()函数:复制字符串)
它的实现,类似于:
char *strdup (const char *s) { char *d = malloc (strlen (s) + 1); // Space for length plus nul if (d == NULL) return NULL; // No memory strcpy (d,s); // Copy the characters return d; // Return the new string}
- C++复制构造函数及三法则
- 三法则,合成赋值操作符,合成复制构造函数
- C++: 复制构造函数
- 三、C++ 复制构造函数
- 构造函数 及复制构造函数
- c/c++整理--复制构造函数和深复制及浅复制
- c/c++整理--复制构造函数和深复制及浅复制
- 复制构造函数的定义及调用
- c++-拷贝构造函数(复制构造函数)
- 复制构造函数与赋值重载(c++)
- c++primer 3/12----复制构造函数
- C++_避免调用复制构造函数
- C++(22)复制构造函数
- C++:复制构造函数___浅拷贝
- C++:复制构造函数的应用
- 【C++】This指针和复制构造函数
- 【学习C++】学习C++ -> 复制构造函数
- 析构 复制 赋值 三法则
- 一步一步教你创建SQL 2005计划任务应用图解教程
- LeetCode 题解(56): Distinct Subsequences
- android图像处理系列之三--图片色调饱和度、色相、亮度处理
- 在Linux下给mysql创建用户并分配权限及问题解决方案
- linux下C与C++混合编译、C++调用C、C++使用C中的函数
- C++复制构造函数及三法则
- jar包中读取资源文件
- 系统测试和集成测试的区别
- 转载-enq:TM-contention
- C#同步SQL Server数据库Schema
- 设计模式之单例模式
- 史上最详细中文版Visual Studio2012安装步骤图解新手教程
- C中的volatile用法
- BeanUtils.populate的作用