当前位置: 首页 > news >正文

C++中浅复制及其存在的问题

C++中浅复制及其存在的问题

之前的示例程序中 MyString 类包含一个指针成员 buffer,它指向动态分配的内存(这些内存是在构造函数中使用 new 分配的,并在析构函数中使用 delete[]进行释放)。复制这个类的对象时,将复制其指针成员,但不复制指针指向的缓冲区,其结果是两个对象指向同一块动态分配的内存。销毁其中一个对象时, delete[]释放这个内存块,导致另一个对象存储的指针拷贝无效。这种复制被称为浅复制,会威胁程序的稳定性,如以下示例程序所示:

#include <iostream>
#include <string.h>
using namespace std;class MyString
{
private:char* buffer;public:MyString(const char* initString) // Constructor{buffer = NULL;if(initString != NULL){buffer = new char [strlen(initString) + 1];strcpy(buffer, initString);}}~MyString() // Destructor{cout << "Invoking destructor, clearing up" << endl;delete [] buffer;}int GetLength() { return strlen(buffer); }const char* GetString(){ return buffer; }
};void UseMyString(MyString str)
{cout << "String buffer in MyString is " << str.GetLength();cout << " characters long" << endl;cout << "buffer contains: " << str.GetString() << endl;return;
}int main()
{MyString sayHello("Hello from String Class");UseMyString(sayHello); return 0;
}

输出:

String buffer in MyString is 23 characters long
buffer contains: Hello from String Class
Invoking destructor, clearing up
Invoking destructor, clearing up
<crash as seen in Figure 9.2>

分析:

在之前的程序中运行正常的 MyString 类, 为何会导致现在这个程序崩溃呢?相比于以前的程序,现在这个程序唯一不同的地方在于,在 main( )中,将使用 MyString 对象 sayHello 的工作交给了函数UseMyString(),如第 44 行所示。在 main( )中将工作交给这个函数的结果是,对象 sayHello 被复制到形参 str,并在 UseMyString( )中使用它。编译器之所以进行复制,是因为函数 UseMyString( )的参数 str 被声明为按值(而不是按引用)传递。对于整型、字符和原始指针等 POD 数据,编译器执行二进制复制,因此 sayHello.buffer 包含的指针值被复制到 str 中,即 sayHello.buffer 和 str.buffer 指向同一个内存单元,如图 9.3 所示。
二进制复制不复制指向的内存单元,这导致两个 MyString 对象指向同一个内存单元。函数UseMyString( )返回时,变量 str 不再在作用域内,因此被销毁。为此,将调用 MyString 类的析构函数,而该析构函数使用 delete[]释放分配给 buffer 的内存(如程序清单 9.8 的第 22 行所示)。这将导致 main( ) 中的对象 sayHello 指向的内存无效,而等 main( )执行完毕时, sayHello 将不再在作用域内,进而被销
毁。但这次第 22 行对不再有效的内存地址调用 delete(销毁 str 时释放了该内存,导致它无效)。正是这种重复调用 delete 导致了程序崩溃。

该文章会更新,欢迎大家批评指正。

推荐一个零声学院的C++服务器开发课程,个人觉得老师讲得不错,
分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容
点击立即学习:C/C++后台高级服务器课程

相关文章:

  • Python 代码格式化工具YAPF 0.17.0问世
  • C++类和对象(七)const成员 及其初始化列表
  • Pytorch图像模型转ONNX后出现色偏问题
  • Visual Studio 2010 软件安装教程(附下载链接)——计算机二级专用编程软件
  • 虽然许多人表示对Windows 11的透明任务栏不满,但有时效果还是挺好的
  • uni-app小程序使用vant
  • 虚拟机VirtualBox添加磁盘
  • React——简便获取经纬度信息
  • 家庭私人影院 - Windows搭建Emby媒体库服务器并远程访问 「无公网IP」
  • 不必安装,快速设计数据库表结构
  • 【gpt redis】原理篇
  • 蓝桥杯官网填空题(含2天数)
  • Java程序设计2023-第三次上机练习
  • pytorch复现_conv2d
  • 读程序员的制胜技笔记04_有用的反模式(下)
  • Android交互
  • Codepen 每日精选(2018-3-25)
  • HTTP中GET与POST的区别 99%的错误认识
  • Java 最常见的 200+ 面试题:面试必备
  • Java反射-动态类加载和重新加载
  • Lucene解析 - 基本概念
  • miniui datagrid 的客户端分页解决方案 - CS结合
  • October CMS - 快速入门 9 Images And Galleries
  • vue 个人积累(使用工具,组件)
  • vue脚手架vue-cli
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • 电商搜索引擎的架构设计和性能优化
  • 缓存与缓冲
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 前嗅ForeSpider采集配置界面介绍
  • 浅谈Golang中select的用法
  • # Swust 12th acm 邀请赛# [ E ] 01 String [题解]
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (3)llvm ir转换过程
  • (C语言)求出1,2,5三个数不同个数组合为100的组合个数
  • (pt可视化)利用torch的make_grid进行张量可视化
  • (附源码)spring boot网络空间安全实验教学示范中心网站 毕业设计 111454
  • (论文阅读笔记)Network planning with deep reinforcement learning
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转) Android中ViewStub组件使用
  • (转)Sublime Text3配置Lua运行环境
  • (轉貼)《OOD启思录》:61条面向对象设计的经验原则 (OO)
  • (最简单,详细,直接上手)uniapp/vue中英文多语言切换
  • .gitattributes 文件
  • .Net Attribute详解(上)-Attribute本质以及一个简单示例
  • .net core 依赖注入的基本用发
  • .NET I/O 学习笔记:对文件和目录进行解压缩操作
  • .net 验证控件和javaScript的冲突问题
  • .NET/C# 中设置当发生某个特定异常时进入断点(不借助 Visual Studio 的纯代码实现)
  • .NetCore部署微服务(二)
  • .net实现头像缩放截取功能 -----转载自accp教程网
  • .net用HTML开发怎么调试,如何使用ASP.NET MVC在调试中查看控制器生成的html?
  • ::
  • @Data注解的作用