C++学习笔记(二十六):c++ 复制与拷贝构造函数

  • 本节介绍拷贝构造函数。
  • 当我们复制数据或对象是一般情况下我们会有两个副本。但当我们仅需要读取数据或者修改一个已经存在的对象时,我们不想去复制一份副本,这样会造成性能的损耗。理解什么时候复制,什么时候不需要复制对提升程序的性能有较大的帮助。
  • 接下来的示例展示复制操作以及不想复制的时候需要怎样去操作。
  • #include <iostream>
    #include <string>
    #include <memory>class Entity
    {
    public:int x, y;Entity(int x, int y){this->x = x;this->y = y;std::cout << "这是构造函数!!!" << std::endl;}~Entity(){std::cout << "这是析构函数!!!" << std::endl;}
    }; int main()
    {//Entity e1(2,5);//Entity e2 = e1;//e2.x = 9;   //此时修改e2中属性变量的值不会影响e1,因为我们复制了一根EntityEntity *e1 = new Entity(2, 5);Entity* e2 = e1;e2->x = 4;  //此时修改e2中属性变量的值会影响e1,因为我们复制了e1的地址到e2,它两指向同样的地址std::cin.get();return 0;
    }
  • 手动实现String类来展示copy操作

  • #include <iostream>
    #include <string>
    #include <memory>//自己实现string来更好的展示拷贝复制构造函数
    class String
    {
    private:char* m_Buffer;unsigned int m_Size;
    public:String(const char* string){m_Size = strlen(string);m_Buffer = new char[m_Size+1]; //+1是因为要添加一个空终止符memcpy(m_Buffer, string, m_Size); m_Buffer[m_Size] = 0;}~String(){delete[] m_Buffer;}friend std::ostream& operator<<(std::ostream& stream, const String& string);
    };
    std::ostream& operator<<(std::ostream& stream, const String& string) 
    {stream << string.m_Buffer;return stream;
    }int main()
    {String s1 = "pcop";/*下面这种方式进行copy操作会导致程序崩溃,因为在此处=操作进行的是浅拷贝,会导致两个String对象中的m_Buffer指向同一块内存地址,这样就会导致析构函数会对同一块内存地址释放两次*/String s2 = s1;  std::cin.get();return 0;
    }
    #include <iostream>
    #include <string>
    #include <memory>//自己实现string来更好的展示拷贝复制构造函数
    class String
    {
    private:char* m_Buffer;unsigned int m_Size;
    public:String(const char* string){m_Size = strlen(string);m_Buffer = new char[m_Size+1]; //+1是因为要添加一个空终止符memcpy(m_Buffer, string, m_Size); m_Buffer[m_Size] = 0;}//拷贝构造函数String(const String& other):m_Size(other.m_Size){m_Buffer = new char[m_Size+1];memcpy(m_Buffer, other.m_Buffer, m_Size+1);}char& operator[] (int index){return m_Buffer[index];}~String(){delete[] m_Buffer;}friend std::ostream& operator<<(std::ostream& stream, const String& string);
    };
    std::ostream& operator<<(std::ostream& stream, const String& string) 
    {stream << string.m_Buffer;return stream;
    }int main()
    {String s1 = "pcop";/** 如果不是先上诉的拷贝构造函数下面这种方式进行copy操作会导致程序崩溃,因为在此处=操作进行的是浅拷贝,会导致两个String对象中的m_Buffer指向同一块内存地址,这样就会导致析构函数会对同一块内存地址释放两次*/String s2 = s1;  /** 下面操作修改s2的时候s1的值也会修改,因为两个String对象的m_Buffer指向同一块内存* 我们在复制中应该的操作是分配一块新的内存用来复制m_Buffer*/s2[2] = 'z';//解决上诉方法可以通过深拷贝来完成,本示例中通过拷贝构造函数来实现std::cout << s1 << std::endl;std::cout << s2 << std::endl;std::cin.get();return 0;
    }
    #include <iostream>
    #include <string>
    #include <memory>//自己实现string来更好的展示拷贝复制构造函数
    class String
    {
    private:char* m_Buffer;unsigned int m_Size;
    public:String(const char* string){m_Size = strlen(string);m_Buffer = new char[m_Size+1]; //+1是因为要添加一个空终止符memcpy(m_Buffer, string, m_Size); m_Buffer[m_Size] = 0;}//拷贝构造函数String(const String& other):m_Size(other.m_Size){std::cout << "Copy String!!!" << std::endl;m_Buffer = new char[m_Size+1];memcpy(m_Buffer, other.m_Buffer, m_Size+1);}char& operator[] (int index){return m_Buffer[index];}~String(){delete[] m_Buffer;}friend std::ostream& operator<<(std::ostream& stream, const String& string);
    };
    std::ostream& operator<<(std::ostream& stream, const String& string) 
    {stream << string.m_Buffer;return stream;
    }void PringString(const String& s)
    {std::cout << s << std::endl;
    }int main()
    {String s1 = "pcop";/** 如果不是先上诉的拷贝构造函数下面这种方式进行copy操作会导致程序崩溃,因为在此处=操作进行的是浅拷贝,会导致两个String对象中的m_Buffer指向同一块内存地址,这样就会导致析构函数会对同一块内存地址释放两次*/String s2 = s1;  /** 下面操作修改s2的时候s1的值也会修改,因为两个String对象的m_Buffer指向同一块内存* 我们在复制中应该的操作是分配一块新的内存用来复制m_Buffer*/s2[2] = 'z';//解决上诉方法可以通过深拷贝来完成,本示例中通过拷贝构造函数来实现/** 如果 PringString(String& s)以下PringString方法调用的时候都会调用String的拷贝构造函数,每次需要分配新的内存会造成很大的性能浪费,我们只是想直接打印PringString方法的参数,不想通过复制。所以在PringString参数传递是直接传递引用  PringString(const String& s)*/PringString(s1);PringString(s2);std::cin.get();return 0;
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/601545.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库服务器如何处理并发访问请求?

在当今的数字化时代&#xff0c;并发访问请求的处理已成为数据库服务器的重要挑战之一。随着应用程序和互联网的普及&#xff0c;数据库服务器需要处理来自大量用户和设备的并发访问请求&#xff0c;这对其性能和可扩展性提出了更高的要求。本文将探讨数据库服务器如何处理并发…

flutter 使用adb 同时连接 多个模拟器

MUMU模拟器 MuMu模拟器官网_安卓12模拟器_网易手游模拟器 传统只需要 连接一个 默认命令是 默认端口是7555 adb connect 127.0.0.1:7555 但是需要同时连接调试多个模拟器的时候 就需要连接多个 这里可以使用自带的多开 多开后 使用 1 是对应多开的序号 这样就可以查看对…

我是谁 whoami

文章目录 我是谁 whoami更多信息 我是谁 whoami 我知道你是谁&#xff0c;但我不知道我是谁&#xff0c;此时whoami可以帮助你&#xff0c;哈哈。 whoami将打印当前用户的名字。与id -un类似。 官方定义为&#xff1a; whoami - print effective userid 用法为&#xff1a; …

Redis基础学习一

1. Redis 入门 1.1. Redis 诞生历程 1.1.1.从一个故事开始 08 年的时候有一个意大利西西里岛的小伙子&#xff0c;笔名 antirez&#xff08;http://invece.org/&#xff09;&#xff0c;创建了一个访客信息网站 LLOOGG.COM。有的时候我们需要知道网站的访问情况&#xff0c;…

高级数据结构:并查集

文章目录 1.什么是并查集&#xff1a;2、并查集的基本结构3.现实问题和代码实现链接4.代码实现 1.什么是并查集&#xff1a; 对于一个集合S{a1,a2,……an-1,an}&#xff0c;这是可以对集合S进一步划分&#xff1a;S1&#xff0c;S2&#xff0c;……&#xff0c;Sm-1&#xff0…

阿里云迁移AWS视频点播技术攻坚

文章目录 &#x1f437; 背景&#x1f9a5; 简述&#x1f425; Aws服务&#x1f99c; AWS CloudFormation&#x1f41e; 问题&#x1f409; 落地方案&#x1f989; Aws vs Aliyun&#x1f344; 避坑指南 &#x1f437; 背景 由于AWS整体成本略低于阿里云&#xff0c;公司决定将…

qt编译管理员权限的程序

MSVC msvc编译的话&#xff0c;只需要在.pro文件中加入以下语句&#xff1a; QMAKE_LFLAGS /MANIFESTUAC:\"level\requireAdministrator\ uiAccess\false\\"MinGW mingw编译的话&#xff0c;有几个步骤&#xff1a; 1、在项目根目录下增加一个文件proce.manifest,…

R 批量对多个变量进行单因素方差分析 批量计算均值±标准差

多个变量批量进行单因素方差 R实现 文章目录 一、批量生成均值标准差 P值二、添加协变量单因素方差分析&#xff0c;生成校正P值三、在分层情况下进行单因素方差分析四、添加协变量和交互项的单因素方差分析&#xff0c;生成交互项的P值 一、批量生成均值标准差 P值 数据结构如…

Android AAudio

文章目录 基本概念启用流程基本流程HAL层对接数据流计时模型调试 基本概念 AAudio 是 Android 8.0 版本中引入的一种音频 API。 AAudio 提供了一个低延迟数据路径。在 EXCLUSIVE 模式下&#xff0c;使用该功能可将客户端应用代码直接写入与 ALSA 驱动程序共享的内存映射缓冲区…

数字图像处理(图像灰度变换、图像直方图及均衡、图像中值滤波、图像空域锐化增强、图像频域滤波)

数字图像处理&#xff08;图像灰度变换、图像直方图及均衡、图像中值滤波、图像空域锐化增强、图像频域滤波&#xff09; 目录 1 图像灰度变换 1.1 灰度线性变换 1.2 图像二值化 1.3 负象变换 1.4 灰度非线性变换 1.5 程序设计流程图 2 图像直方图及均衡 2.1 直方图 2…

Linux 服务器磁盘满了怎么办?详细清理大文件指南

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

Agilent安捷伦E4407B频谱分析仪26.5GHz

E4407B是安捷伦ESA-E系列频谱分析仪&#xff0c;它是一款能够适应未来需要的中性能频谱分析仪解决方案。该系列在测量速度、动态范围、精度和功率分辨能力上&#xff0c;都为类似价位的产品建立了性能标准。其灵活的平台设计使得研发、制造和现场服务工程师能够自定义产品&…

特征工程筛选重要变量

特征筛选主要分为3个方法&#xff1a;过滤法、嵌入法&#xff08;经典的一些树模型比如xgboost&#xff09;、包裹法&#xff08;经典的RFECV&#xff0c;RFE递归特征消除法&#xff09; 过滤法更快速&#xff0c;但更粗糙。 包装法和嵌入法更精确&#xff0c;比较适合具体到算…

【代码随想录】刷题笔记Day46

前言 刚考完自辩&#xff0c;Chat回答举例什么的真方便。早上做组会PPT去了&#xff0c;火速来刷题&#xff01; 139. 单词拆分 - 力扣&#xff08;LeetCode&#xff09; 单词是物品&#xff0c;字符串s是背包&#xff0c;单词能否组成字符串s&#xff0c;就是问物品能不能把…

Kotlin: Jetpack — ViewModel简单应用

ViewModel 概览 Android Jetpack 的一部分。 ViewModel 类是一种业务逻辑或屏幕级状态容器。它用于将状态公开给界面&#xff0c;以及封装相关的业务逻辑。 它的主要优点是&#xff0c;它可以缓存状态&#xff0c;并可在配置更改后持久保留相应状态。这意味着在 activity 之…

Android studio ViewPager2应用设计

一、ViewPager2应用场景: ViewPager2是一个功能强大的滑动容器,提供灵活的页面切换和布局定制功能,使得应用程序界面更加丰富和交互性强,主要应用于以下场景: 1)、实现引导页或欢迎页:ViewPager2可用于创建引导页/欢迎页,让用户通过滑动浏览介绍应用程序功能/展示欢迎…

SpringBoot学习(五)-Spring Security配置与应用

注&#xff1a;此为笔者学习狂神说SpringBoot的笔记&#xff0c;其中包含个人的笔记和理解&#xff0c;仅做学习笔记之用&#xff0c;更多详细资讯请出门左拐B站&#xff1a;狂神说!!! Spring Security Spring Security是一个基于Java的开源框架&#xff0c;用于在Java应用程…

【深度学习】cv领域中各种loss损失介绍

文章目录 前言一、均方误差二、交叉熵损失三、二元交叉熵损失四、Smooth L1 Loss五、IOU系列的loss 前言 损失函数是度量模型的预测输出与真实标签之间的差异或误差&#xff0c;在深度学习算法中起着重要作用。具体作用&#xff1a; 1、目标优化&#xff1a;损失函数是优化算法…

Leetcode2807. 在链表中插入最大公约数

Problem: 2807. 在链表中插入最大公约数 文章目录 题目思路注意点Code 题目思路 模拟插入流程&#xff1a; 检测当前节点是否有后置结点&#xff1b;将当前结点与后置结点的值做最大公约数处理得到新结点的值&#xff0c;然后插入到当前结点之后&#xff1b;再将检测结点向后…

文件归类妙招:用关键字替换改扩展名方法,文件重命名技巧

在日常工作中&#xff0c;文件的数量会随着时间的推移不断增加。如果文件没有得到适当的归类和整理&#xff0c;就会导致很难找到所需的文件。所以文件归类是非常重要的任务。现在来看云炫文件管理器一些实用的文件归类妙招&#xff1a;用关键字替换修改文件扩展名的方法&#…