news 2026/4/30 15:58:58

C++拷贝构造与运算符重载实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++拷贝构造与运算符重载实战
四、拷贝构造函数

如果一个构造函数的第⼀个参数是自身类类型的引用,且任何额外的参数都有默认值,则此构造函数也叫做拷贝构造函数,也就是说拷贝构造是⼀个特殊的构造函数。

拷贝构造使用于当前类型的对象去初始化当前类型的另一个要创建的对象,换句话来说就是当你完成的是自身这个类型的拷贝初始化就会用拷贝构造,拷贝构造函数是构造函数的一个重载。

拷贝构造函数的特点:

  1. 拷贝构造函数是构造函数的⼀个重载。
  2. 拷贝构造函数的第⼀个参数必须是当前类类型对象的引用,使用传值方式编译器直接报错,因为语法逻辑上会引发无穷递归调用。 拷贝构造函数也可以多个参数,但是第⼀个参数必须是类类型对象的引用,后面的参数必须有缺省值。
  3. C++规定自定义类型对象进行拷贝行为必须调用拷贝构造,所以这里自定义类型传值传参和传值返回都会调用拷贝构造完成。
  4. 若未显式定义拷贝构造,编译器会生成自动生成拷贝构造函数。自动生成的拷贝构造对内置类型成员变量会完成值拷贝/浅拷贝(⼀个字节⼀个字节的拷贝),对自定义类型成员变量会调用他的拷贝构造。

既然拷贝构造函数是构造函数的一个重载,接下来,我们来写一个拷贝构造函数:

代码语言:javascript

AI代码解释

class Date { public: Date(int year = 1, int month = 1, int day = 1) { _year = year; _month = month; _day =day; } ~Date() { cout << "~Date()" << endl; } Date(Date& d) { _year = d._year; _month = d._month; _day = d._day; } void Print() { cout << _year << "/" << _month << "/" << _day<<endl; } private: int _year; int _month; int _day; }; int main() { Date d1(2025,8,4); Date d2(d1);//拷贝构造 d2.Print(); return 0; }

我们看到,在拷贝构造特点中的第二点中写到:拷贝构造函数的第⼀个参数必须是类类型对象的引用。

那为什么要用引用传参?为什么不能用传值传参?

有人会说,func(d1)不是在调用函数吗?怎么跑到拷贝构造上面去了 ?在调用一个函数前,编译器会先完成传参(传值传参就是拷贝,对于自定义类型的拷贝,都是调用拷贝构造来完成拷贝的),然后再去调用这个函数

总结:C++规定自定义类型对象进行拷贝行为必须调用拷贝构造,所以这里自定义类型传值传参和传值返回都会调用拷贝构造完成。

如果拷贝构造函数使用传值调用,会形成无穷递归:

每次要调用靠别构造函数之前要进行传值传参,传值传参是一种拷贝,又形成一个新的拷贝构造,调用新的拷贝构造之前要进行传值传参,传值传参是一种拷贝,又形成一个新的拷贝构造,以此下去,就形成了无穷递归,但是当我们使用引用传参时,就不需要进行拷贝构造,这样就不会形成无穷递归了,所以我们使用引用传参。

当我们使用拷贝构造函数的时候,引用传参建议使用const:

代码语言:javascript

AI代码解释

class Date { public: Date(int year = 1, int month = 1, int day = 1) { _year = year; _month = month; _day =day; } ~Date() { cout << "~Date()" << endl; } //加上const可以避免权限放大 Date(const Date& d) { _year = d._year; _month = d._month; _day = d._day; } void Print() { cout << _year << "/" << _month << "/" << _day<<endl; } private: int _year; int _month; int _day; }; void func(Date d) { } int main() { Date d1(2025,8,4); func(d1); return 0; }

通过上面的学习,我们知道拷贝构造函数是适用于当前类型的对象去初始化当前类型的另一个要创建的对象,比如上面的Date类,那如果说拷贝构造仅仅适用于这种一一拷贝,那拷贝构造是不是有点太简单了。接下来,我们来看一下稍微难点的应用:

代码语言:javascript

AI代码解释

class Stack { public: Stack(int n=4) { _a = (int*)malloc(sizeof(int) * n); _top = 0; _capacity = n; } ~Stack() { if (_a) { free(_a); _a = nullptr; _top = 0; _capacity = 0; } } Stack(const Stack& s) { _a = s._a; _top = s._top; _capacity = s._capacity; } private: int* _a; int _top; int _capacity; }; int main() { Stack s1; Stack s2(s1); return 0; }

ok,我们创建了一个栈,然后使用拷贝构造函数给s2进行初始化,在这个初始化的过程中会发生什么不可预期的东西呢?

我们看到红方框内的地址是一样的。那就有同学会问了,地址一样会有什么问题吗?ok,当你使用编译器进行调试的时候,就会发现编译器崩了:

这是什么原因呢?当我们调试编译器的时候,返现拷贝构造时没有发生任何错误,但是当我们执行到第二次析构函数的时候,此时发生了报错,只是因为编译器对空间进行了两次释放(同一块空间)

那为什么会对空间进行两次释放呢?

那我们该如何解决呢?对于这种情况,我们要使用深拷贝:不仅仅是对成员拷贝,还是对指向资源空间数据进行拷贝

代码语言:javascript

AI代码解释

class Stack { public: Stack(int n=4) { _a = (int*)malloc(sizeof(int) * n); _top = 0; _capacity = n; } ~Stack() { if (_a) { free(_a); _a = nullptr; _top = 0; _capacity = 0; } } //深拷贝 Stack(const Stack& s) { _a = (int*)malloc(sizeof(int) * s._capacity); if (_a == nullptr) { perror("malloc fail!"); exit(1); } //将数据拷贝过去 memcpy(_a,s._a,sizeof(int)* s._capacity); _top = s._top; _capacity = s._capacity; } private: int* _a; int _top; int _capacity; }; int main() { Stack s1; Stack s2(s1); return 0; }

前面我们学习的构造函数和析构函数,当我们不写时,编译器自动生成的构造函数和析构函数对内置类型成员不做处理,自定类型成员会调用他的析构函数。但是拷贝构造有点不同:若未显式定义拷贝构造,编译器会生成自动生成拷贝构造函数。自动生成的拷贝构造对内置类型成员变量会完成值拷贝/浅拷贝(⼀个字节⼀个字节的拷贝),对自定义类型成员变量会调用他的拷贝构造。

www.dongchedi.com/article/7596039640361206334
www.dongchedi.com/article/7596036566536520217
www.dongchedi.com/article/7596038202335707673
www.dongchedi.com/article/7596036203376919065
www.dongchedi.com/article/7596036558738833982
www.dongchedi.com/article/7596037454990426648
www.dongchedi.com/article/7596035720197227033
www.dongchedi.com/article/7596037630450565657
www.dongchedi.com/article/7596035789235307032
www.dongchedi.com/article/7596035144272740888
www.dongchedi.com/article/7596035023862596121
www.dongchedi.com/article/7596035565267993112
www.dongchedi.com/article/7596034656816972312
www.dongchedi.com/article/7596035038500733464
www.dongchedi.com/article/7596035446715597374
www.dongchedi.com/article/7596033910857925144
www.dongchedi.com/article/7596032917361951257
www.dongchedi.com/article/7596033810694160921
www.dongchedi.com/article/7596034317558628926
www.dongchedi.com/article/7596026007967416857
www.dongchedi.com/article/7596026266785186366
www.dongchedi.com/article/7596024522248176190
www.dongchedi.com/article/7596024522244014654
www.dongchedi.com/article/7596024000137380377
www.dongchedi.com/article/7596010701236306456
www.dongchedi.com/article/7596012418107556414
www.dongchedi.com/article/7595895683039887897

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/25 6:08:00

Qwen1.5-0.5B-Chat性能优化:让轻量级对话速度提升50%

Qwen1.5-0.5B-Chat性能优化&#xff1a;让轻量级对话速度提升50% 在边缘计算和资源受限场景日益普及的今天&#xff0c;如何在低算力设备上实现流畅的AI对话体验&#xff0c;成为开发者关注的核心问题。尤其当业务需要部署在无GPU支持的服务器、嵌入式设备或系统盘环境中时&am…

作者头像 李华
网站建设 2026/4/29 16:06:21

Axure RP 11完整汉化终极指南:3步实现专业级中文界面

Axure RP 11完整汉化终极指南&#xff1a;3步实现专业级中文界面 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包&#xff0c;不定期更新。支持 Axure 9、Axure 10。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还…

作者头像 李华
网站建设 2026/4/24 0:42:30

5分钟精通原神智能助手:开源工具箱的终极配置指南

5分钟精通原神智能助手&#xff1a;开源工具箱的终极配置指南 【免费下载链接】Snap.Hutao 实用的开源多功能原神工具箱 &#x1f9f0; / Multifunctional Open-Source Genshin Impact Toolkit &#x1f9f0; 项目地址: https://gitcode.com/GitHub_Trending/sn/Snap.Hutao …

作者头像 李华
网站建设 2026/4/27 12:14:34

5分钟掌握Snap.Hutao原神工具箱:从新手到高手的完整指南

5分钟掌握Snap.Hutao原神工具箱&#xff1a;从新手到高手的完整指南 【免费下载链接】Snap.Hutao 实用的开源多功能原神工具箱 &#x1f9f0; / Multifunctional Open-Source Genshin Impact Toolkit &#x1f9f0; 项目地址: https://gitcode.com/GitHub_Trending/sn/Snap.H…

作者头像 李华
网站建设 2026/4/22 12:06:00

智能编程助手完整功能解锁指南:快速提升开发效率的终极方案

智能编程助手完整功能解锁指南&#xff1a;快速提升开发效率的终极方案 【免费下载链接】cursor-free-vip [Support 0.45]&#xff08;Multi Language 多语言&#xff09;自动注册 Cursor Ai &#xff0c;自动重置机器ID &#xff0c; 免费升级使用Pro 功能: Youve reached you…

作者头像 李华
网站建设 2026/4/21 14:44:43

Day 47 注意力热图可视化

对比CNN不同卷积层的热图可视化结果 CNN&#xff1a; import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pyplot as plt import numpy as np# 设置中…

作者头像 李华