看下面一个表示string对象的类:

// 一个很简单的string类
class string {
public:string(const char *value);~string();...                           // 没有拷贝构造函数和operator=private:char *data;
};string::string(const char *value)
{if (value) {data = new char[strlen(value) + 1];strcpy(data, value);}else {data = new char[1];*data = '\0';}
}inline string::~string() { delete [] data; }

请注意这个类里没有声明赋值操作符和拷贝构造函数。这会带来一些不良后果。

如果这样定义两个对象:

string a("hello"); string b("world");

其结果就会如下所示:

a:  data——> "hello\0"

b:  data——> "world\0"

对象a的内部是一个指向包含字符串"hello"的内存的指针,对象b的内部是一个指向包含字符串"world"的内存的指针。如果进行下面的赋值:

b = a;

因为没有自定义的operator=可以调用,c++会生成并调用一个缺省的operator=操作符(见条款45)。这个缺省的赋值操作符会执行从a的成员到b的成员的逐个成员的赋值操作

这种情况下至少有两个问题。第一,b曾指向的内存永远不会被删除,因而会永远丢失。这是产生内存泄漏的典型例子。第二,现在a和b包含的指针指向同一个字符串,那么只要其中一个离开了它的生存空间,其析构函数就会删除掉另一个指针还指向的那块内存。

拷贝构造函数的情况和赋值操作符还有点不同。在传值调用的时候,它会产生问题。当然正如条款22所说明的,一般很少对对象进行传值调用,但还是看看下面的例子:

void donothing(string localstring) {}
string s = "the truth is out there";
donothing(s);//缺省拷贝构造函数,直接复制指针,当函数返回时,指针指向的内存被释放

因为被传递的localstring是一个值,它必须从s通过(缺省)拷贝构造函数进行初始化。于是localstring拥有了一个s内的指针的拷贝。当donothing结束运行时,localstring离开了其生存空间,调用析构函数。其结果也将是:s包含一个指向localstring早已删除的内存的指针。

用delete去删除一个已经被删除的指针,其结果是不可预测的。

解决这类指针混乱问题的方案在于,只要类里有指针时,就要写自己版本的拷贝构造函数和赋值操作符函数。在这些函数里,你可以拷贝那些被指向的数据结构,从而使每个对象都有自己的拷贝(深拷贝);或者你可以采用某种引用计数机制(见条款 m29)去跟踪当前有多少个对象指向某个数据结构。引用计数的方法更复杂,而且它要求构造函数和析构函数内部做更多的工作,但在某些(虽然不是所有)程序里,它会大量节省内存并切实提高速度。

转载于:https://www.cnblogs.com/ljygoodgoodstudydaydayup/p/3901142.html

条款十一: 为需要动态分配内存的类声明一个拷贝构造函数和一个拷贝赋值运算符...相关推荐

  1. 声明对象_静态变量(使用同一个类声明的对象可以共享一个值)

    要在属于同一种类的对象之间共享数据值,可以使用static. namespace demo3{ class point //定义点 { public int x; public int y; } cl ...

  2. C/C++动态分配内存

    本博客对以下几篇博客进行总结归纳: https://blog.csdn.net/Errors_In_Life/article/details/78889951 https://blog.csdn.ne ...

  3. effective c++条款11扩展——关于拷贝构造函数和赋值运算符

    effective c++条款11扩展--关于拷贝构造函数和赋值运算符 作者:冯明德 重点:包含动态分配成员的类 应提供拷贝构造函数,并重载"="赋值操作符. 以下讨论中将用到的例 ...

  4. 类的6个默认成员函数:构造函数、析构函数、拷贝构造函数、重载运算符、三/五法则

    文章目录 6个默认成员函数 构造函数 概念 默认构造函数的类型 默认实参 概念 默认实参的使用 默认实参声明 全局变量作为默认实参 某些类不能依赖于编译器合成的默认构造函数 第一个原因 第二个原因 第 ...

  5. 利用类定义一个指针会调用默认构造函数吗_C++的拷贝构造函数

    拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象.拷贝构造函数通常用于: 通过使用另一个同类型的对象来初始化新创建的对象. 复制对象把它作为参数传递给 ...

  6. C++ 笔记(17)— 类和对象(构造函数、析构函数、拷贝构造函数)

    1. 构造函数 构造函数是一种特殊的函数(方法),在根据类创建对象时被调用.构造函数是一种随着对象创建而自动被调用的函数,它的主要用途是为对象作初始化. 构造函数的名称与类的名称是完全相同的,并且不会 ...

  7. C++ 类和对象(二):构造函数、析构函数、拷贝构造函数、运算符重载

    构造函数 析构函数 拷贝构造函数 运算符重载 class Date {}; 可以看到,上面那个类没有任何成员,是一个空类,但是它真的什么都没有吗?其实一个类在我们不写的情况下,都会生成6个默认的成员函 ...

  8. 浅谈深浅拷贝问题(这里只针对拷贝构造函数和赋值运算符重载)和简易srting类模拟实现

    浅谈深浅拷贝问题(这里只针对拷贝构造函数和赋值运算符重载)和简易srting类模拟实现 文章目录 浅谈深浅拷贝问题(这里只针对拷贝构造函数和赋值运算符重载)和简易srting类模拟实现 一.什么是浅拷 ...

  9. 【C++】类和对象——拷贝构造函数

    文章目录 什么是拷贝构造函数 为什么拷贝构造要传引用 默认拷贝构造函数 浅拷贝和深拷贝 编译器可能的优化 自定义类型做函数返回值时传值返回 自定义类型做函数参数时传值调用 总结一下 什么是拷贝构造函数 ...

  10. C++ 类中的 构造函数、拷贝构造函数、析构函数

    一.构造函数 ① 概念 构造函数就是和类名一样,而且是没有返回值的函数.如下所示:class demo_class{public:demo_class();//构造函数 如果不指定属性,则默认为私有的 ...

最新文章

  1. 新报告直指3大安全威胁 企业需小心应对
  2. python——no module named XX
  3. c语言程序为什么运行一半就自动关闭了,C语言为什么程序运行一半就出现停止工作...
  4. html过滤 -java_PHP过滤各种html标签
  5. [TC]SRM615 div1 250 AmebaDiv1
  6. 游戏开发之C++多继承及虚继承(C++基础)
  7. ADS8364 VHDL程序正式版
  8. 时序轮转的意思_《九州仙魔志》-烛龙:凡人的昼夜轮转,都在它眼睛开合之间...
  9. android 点击后退按钮,android – 按下后退按钮后重新选择正确的NavigationView菜单项...
  10. 基于HoG 的图像特征提取及其分类研究
  11. 路由器wifi信号测试软件,常用路由器WIFI测速效果比对
  12. python爬虫读取pdf_python中使用tabula爬取pdf数据并导出表格
  13. xmanager登陆linux黑屏,用xmanager软件登陆linux的方法
  14. nrf52x 二 GPIOTE
  15. 第六周作业 百词斩对比可可英语
  16. 关于我想写个脚本,最后却搞了个桌面宠物这件事(一)
  17. 下载IE6安装文件到本地的方法
  18. 在Windows 使用Administrator账户
  19. Java11 ZGC 和 Java12 Shenandoah 介绍:苟日新、日日新、又日新
  20. 征服者驱动程序下载_征服者纸上的五种美丽免费字体

热门文章

  1. 孙杨事件的几点事实!
  2. 有些人,理他就输了!
  3. 福利 | 限时免费体验 Google 官方 Android 课程
  4. ios识别人脸自动拍照_证件识别是指能实现拍照自动输入身份信息
  5. JSP-Runoob:JSP 文件上传
  6. P1043 数字游戏
  7. 使用socket()函数创建套接字
  8. Adaboost算法结合Haar-like特征
  9. 利用vertical-align:middle实现在整个页面居中
  10. 在其他的电脑上配置绿色Jre+tomcat运行环境