C++指南——拷贝构造函数和赋值运算符重载

文章目录

    • 1 举个例子(问题由来)
    • 2 拷贝构造函数与构造函数不同
    • 3 默认拷贝构造函数是浅拷贝
    • 4 默认赋值运算符是浅拷贝

1 举个例子(问题由来)

在C++中,使用Car car2 = car1; 这种形式的语句被称为拷贝构造(用一个对象初始化一个新对象),它并不总是会调用构造函数。这个语法实际上是使用拷贝构造函数来创建一个新对象 car2,并将其初始化为另一个对象 car1 的副本。如果你没有提供自定义的拷贝构造函数,C++ 会生成一个默认的拷贝构造函数,该函数会逐个成员进行复制。

而对于 Car car2; car2 = car1;,这是两个步骤的组合。首先,Car car2; 创建了一个未初始化的对象 car2,然后 car2 = car1; 执行了赋值操作,这会调用赋值运算符 (operator=)。如果你没有提供自定义的赋值运算符,C++ 会生成默认的赋值运算符,该运算符也会逐个成员进行复制。

所以,两者的行为略有不同。前者是在对象初始化的时候就进行了拷贝构造,而后者是在对象已经创建后再进行了赋值操作。如果你的类有复杂的资源管理或者需要进行深拷贝,你可能需要实现自定义的拷贝构造函数和赋值运算符来确保正确的行为。(就是说,成员的浅拷贝不合法时,可以对拷贝构造函数和赋值运算符函数进行定义)

2 拷贝构造函数与构造函数不同

  1. 构造函数 (Constructor): 构造函数是在创建对象时调用的特殊成员函数。它用于初始化对象的各个成员变量,为对象分配资源,或执行其他必要的初始化操作。构造函数通常在对象被声明时自动调用。

    class Car {
    public:// 构造函数Car() {// 初始化操作}
    };// 创建对象时构造函数被调用
    Car car1;
    
  2. 拷贝构造函数 (Copy Constructor): 拷贝构造函数是一种特殊的构造函数,用于创建一个对象并将其初始化为另一个对象的副本。拷贝构造函数通常在以下情况下调用:

    • 通过值传递的方式传递对象给函数。
    Car mycar;
    func1(mycar);
    ....//func1的定义
    void func1(car c){.....}
    
    • 通过值返回对象。(该情况可能赋值运算符也会被调用)
Car mycar;
mycar = func2(); //赋值运算符被调用
Car mycar3 = func2() //拷贝构造函数被调用//func2的定义
Car func(){Car c;....return c;}
  • 通过另一个对象初始化一个新对象。
class Car {
public:// 拷贝构造函数Car(const Car& other) {// 复制 other 的成员变量到当前对象}
};// 使用拷贝构造函数创建 car2,并将其初始化为 car1 的副本
Car car2 = car1;

总结来说,构造函数用于对象的初始化,而拷贝构造函数用于在创建对象时将其初始化为另一个对象的副本。拷贝构造函数的存在使得对象能够在不同的上下文中进行复制,并且通常在涉及到对象的复制或传递时起到关键作用。

3 默认拷贝构造函数是浅拷贝

C++ 默认生成的拷贝构造函数执行的是浅拷贝(shallow copy)。浅拷贝意味着拷贝构造函数只是逐个成员地复制源对象的成员变量的值到目标对象,而不考虑这些成员变量的内部结构。

如果类中包含指针或动态分配的资源,浅拷贝可能导致问题,因为两个对象将指向相同的内存区域。这意味着如果其中一个对象修改了共享的资源,另一个对象也会受到影响。

为了避免这个问题,当类中包含指针或动态分配的资源时,通常需要手动实现自定义的拷贝构造函数来执行深拷贝(deep copy)。深拷贝会为目标对象分配新的内存,并将源对象的数据复制到新的内存中,以确保两个对象相互独立

以下是一个示例,展示了使用默认生成的拷贝构造函数可能引起的问题:

#include <iostream>class DynamicArray {
public:DynamicArray(int size) {size_ = size;data_ = new int[size_];}~DynamicArray() {delete[] data_;}private:int* data_;int size_;
};class MyClass {
public:// 默认生成的拷贝构造函数是浅拷贝// 这可能导致两个对象共享相同的内存,造成问题// 需要手动实现深拷贝MyClass(const MyClass& other) {// 默认生成的拷贝构造函数执行的是浅拷贝// data_ 指针将被复制,两个对象将共享相同的内存data_ = other.data_;}private:DynamicArray* data_;
};int main() {MyClass obj1(5);MyClass obj2 = obj1; //拷贝构造函数被调用// 此时 obj1 和 obj2 共享相同的 DynamicArray 对象// 修改其中一个对象可能会影响另一个对象return 0;
}

在上述示例中,如果 MyClass 的对象通过默认生成的拷贝构造函数进行复制,它们将共享相同的 DynamicArray 对象,可能导致潜在的问题。

4 默认赋值运算符是浅拷贝

C++ 默认生成的赋值运算符 (operator=) 也执行浅拷贝。这意味着默认情况下,赋值运算符只是逐个成员地复制源对象的成员变量的值到目标对象,而不考虑这些成员变量的内部结构。

如果类中包含指针或动态分配的资源,浅拷贝可能导致问题,因为两个对象将指向相同的内存区域。对其中一个对象的修改可能会影响另一个对象。

与拷贝构造函数一样,当类中包含指针或动态分配的资源时,通常需要手动实现自定义的赋值运算符来执行深拷贝,以确保两个对象相互独立

以下是一个示例,展示了使用默认生成的赋值运算符可能引起的问题:

#include <iostream>class DynamicArray {
public:DynamicArray(int size) {size_ = size;data_ = new int[size_];}~DynamicArray() {delete[] data_;}private:int* data_;int size_;
};class MyClass {
public:// 默认生成的赋值运算符是浅拷贝// 这可能导致两个对象共享相同的内存,造成问题// 需要手动实现深拷贝MyClass& operator=(const MyClass& other) {// 默认生成的赋值运算符执行的是浅拷贝// data_ 指针将被复制,两个对象将共享相同的内存if (this != &other) {data_ = other.data_;}return *this;}private:DynamicArray* data_;
};int main() {MyClass obj1(5);MyClass obj2;// 使用默认生成的赋值运算符进行赋值obj2 = obj1;// 此时 obj1 和 obj2 共享相同的 DynamicArray 对象// 修改其中一个对象可能会影响另一个对象return 0;
}

在上述示例中,如果 MyClass 的对象通过默认生成的赋值运算符进行赋值,它们将共享相同的 DynamicArray 对象,可能导致潜在的问题。

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

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

相关文章

[算法]使用aes进行数据加密

一、需求 有一段信息需要进行安全加密。 二、方案 对称加密和非对称加密两种方案&#xff0c;其中由于公钥密钥的管理还未形成规范&#xff0c;因此考虑使用对称加密。其中&#xff0c;对称加密算法使用openssl中&#xff0c;关于aes的部分&#xff0c;输出结果为128位数据。…

【青书学堂】 2023年第二学期 刑法学(总论)(直播课) 作业

【青书学堂】 2023年第二学期 刑法学(总论)(直播课) 作业 为了方便日后复习&#xff0c;青书学堂成人大专试题整理。 若有未整理的课程&#xff0c;请私信我补充&#xff0c;欢迎爱学习的同学们收藏点赞关注&#xff01;文章内容仅限学习使用&#xff01;&#xff01;&#xff…

自然语言处理中的语言模型

知乎好文章&#xff0c;建议参考学习语言模型 语言模型&#xff08;Language Model, LM&#xff09;是用于计算或预测一系列词语&#xff08;句子或文本段落&#xff09;出现概率的统计模型。它们能够基于已知的词序列来预测下一个词或者评估一个句子的语言学合理性。 发展历程…

【代码学习】einops,更简单的张量变化

官方教程&#xff1a;https://github.com/arogozhnikov/einops/blob/master/docs/2-einops-for-deep-learning.ipynb 常见操作&#xff1a; 维度变换 rearrange 维度变换 y rearrange(x, b c h w -> b h w c) # 已经 表明 x的每个轴 变量 b c h w guess(y.shape)flatten…

oracle-undo

tips&#xff1a;串行化隔离级别&#xff1a;事务开始后&#xff0c;对一张表不会被别人影响&#xff0c;对于审计工作比较有用&#xff0c;避免了幻读。 undo表空间&#xff1a;自动生成段&#xff0c;自动生成区&#xff0c;自动维护的&#xff0c;不像一般的表空间&#xff…

独立式键盘控制的4级变速流水灯

#include<reg51.h> // 包含51单片机寄存器定义的头文件 unsigned char speed; //储存流水灯的流动速度 sbit S1P1^4; //位定义S1为P1.4 sbit S2P1^5; //位定义S2为P1.5 sbit S3P1^6; //位定义S3为P1.6 sbit S4P1^7; //位…

泽攸科技完全自主研制的电子束光刻机取得阶段性成果

国产电子束光刻机实现自主可控&#xff0c;是实现我国集成电路产业链自主可控的重要一环。近日&#xff0c;泽攸科技联合松山湖材料实验室开展的全自主电子束光刻机整机的开发与产业化项目取得重大进展&#xff0c;成功研制出电子束光刻系统&#xff0c;实现了电子束光刻机整机…

rime中州韵小狼毫 生字注音滤镜 汉字注音滤镜

在中文环境下&#xff0c;多音字是比较常见的现象。对于一些不常见的生僻字&#xff0c;或者一些用于地名&#xff0c;人名中的常见字的冷门读音&#xff0c;如果不能正确的阅读&#xff0c;例如把 荥阳 读成了 miāo yng&#xff0c;则会怡笑大方。 今天我们在rime中州韵小狼…

python自动化运维管理拓扑

目录 1、简介 2、实验环境 3、拓扑图 4、需求及其代码 4.1、测试连通性 4.2、远程登陆 4.3、配置loopback 4.4、监控内存使用率 4.5、自动化巡检内存使用率 4.6、自动化配置snmp服务 4.7、提取分析字符串 &#x1f343;作者介绍&#xff1a;双非本科大三网络工程专业…

2024 年 20+ 个 Node.js 开发工具

2024了&#xff0c;你准备好提升你的Node.js开发体验了吗&#xff1f;有了合适的工具集&#xff0c;你可以将你的项目提升到新的高度&#xff0c;简化你的工作流程&#xff0c;创建强大的、高性能的应用程序。这篇全面的指南将向你介绍Node.js开发的顶级工具&#xff0c;提供使…

网络流量分析与故障分析

1.网络流量实时分析 网络监控 也snmp协议 交换机和服务器打开 snmp就ok了 MRTG或者是prgt 用于对网络流量进行实时监测&#xff0c;可以及时了解服务器和交换机的流量&#xff0c;防止因流量过大而导致服务器瘫痪或网络拥塞。 原理 通过snmp监控 是一个…

外汇网站主要业务逻辑梳理

上图为工行ICBC的外汇保证金交易界面。 当需要买入帐户欧元&#xff08;欧元人民币&#xff09;时&#xff0c;买入100欧元&#xff0c;因为没有杠杆&#xff0c;虽然欧元中间价是782.34&#xff0c;但实际需要支付783.14元人民币的保证金&#xff0c;这个兑换不是真实的外汇兑…

2.8 EXERCISES

如果我们想使用每个线程来计算向量加法的一个输出元素&#xff0c;那么将线程/块索引映射到数据索引的表达式是什么&#xff1f; 答&#xff1a;C 假设我们想用每个线程来计算向量加法的两个&#xff08;相邻&#xff09;元素。将线程/块索引映射到i&#xff08;由线程处理的…

[MySQL] 数据库的主从复制和读写分离

一、mysql主从复制和读写分离的相关知识 1.1 什么是读写分离? 读写分离&#xff0c;基本的原理是让主数据库处理事务性增、改、删操作( INSERT、UPDATE、DELETE) &#xff0c;而从数据库处理SELECT查询操作。数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。…

React Hooks的useState、useRef使用

React Hooks 是 React 16.8 版本引入的新特性&#xff0c;它允许你在不编写 class 的情况下使用 state 和其他 React 特性。其中&#xff0c;useState 和 useRef 是两个常用的 Hooks。 1. useState useState 是一个允许你在函数组件中添加 state 的 Hook。 使用说明&#xf…

Windows11下载安装nacos(2.3.0)详解

一、环境要求 windows7以上 jdk8及以上版本&#xff0c;并且配置了JAVA_HOME环境变量 二、nacos下载解压 release版本地址:Releases alibaba/nacos GitHub 下载后解压即可&#xff0c;上面的tar.gz是linux版本 解压后如下 nacos自己内置有数据库derby&#xff0c;我用的是…

使用 matlab 求解最小二乘问题

有约束线性最小二乘 其标准形式为&#xff1a; min ⁡ x 1 2 ∥ C x − d ∥ 2 2 \mathop {\min }\limits_x \quad \frac{1}{2}\left\| Cx-d \right\|_2^2 xmin​21​∥Cx−d∥22​ 约束条件为&#xff1a; A ⋅ x ≤ b A e q ⋅ x b e q l b ≤ x ≤ u b \begin{aligned} …

RAG 全链路评测工具 —— Ragas

RAG是目前比较火热的一个概念。对应的应用如雨后春笋般涌出。我们在实际的探索中&#xff0c;可能会有各种各样的优化方案。但是优化是否有用呢&#xff1f;模型影响会有多大呢&#xff1f; 我们需要一把尺子&#xff0c;来做全链路的衡量。才能够得出&#xff0c;到底应该朝哪…

光纤知识总结

1光纤概念&#xff1a; 光导纤维&#xff08;英语&#xff1a;Optical fiber&#xff09;&#xff0c;简称光纤&#xff0c;是一种由玻璃或塑料制成的纤维&#xff0c;利用光在这些纤维中以全内反射原理传输的光传导工具。 微细的光纤封装在塑料护套中&#xff0c;使得它能够…

Kotlin 操作符重载

Kotlin 操作符重载 Kotlin 通过 operator 关键字 修饰 操作符函数&#xff0c;来实现 操作符重载。 操作&#xff0c;对应 inc 函数&#xff0c;-- 操作符&#xff0c;对应 dec 函数 举例&#xff0c;Point 类 实现 操作符重载&#xff1a; class Point {operator fun inc()…