资讯动态

小学生学C++编程语法知识(为什么C++需要拷贝构造函数?)

发布时间:2026/8/5 8:15:48 来源:尧图企业网站定制
《为什么C需要拷贝构造函数》——从对象复制到 Rule of Three三法则同学们上一节我们学习了浅拷贝深拷贝我们知道如果一个类里面有指针普通复制可能会出现问题。那么问题来了C为什么要设计“拷贝构造函数”今天我们就像侦探一样一步步找到答案。一、先回忆什么是对象在C中类class Student { };像是一张制造学生的图纸。对象Student s1;就是根据图纸制造出来的学生。例如class Student { public: int age; };创建Student s1; s1.age10;内存s1 age ┌────┐ │ 10 │ └────┘二、为什么需要复制对象现实中小明有一本笔记数学笔记小红想要一样的数学笔记怎么办复制C也是一样。例如Student s1; Student s2s1;意思创建s2并复制s1。三、如果没有拷贝构造函数会怎样先看简单情况。例1普通变量class Student { public: int age; }; int main() { Student a; a.age10; Student ba; }C自动帮我们b.agea.age;结果a: age10 b: age10没有问题。为什么因为age里面存的是真正的数据复制数据即可。四、麻烦来了指针成员看class Student { public: int *score; };这里score不是分数。score是一个地址。例如Student a; a.scorenew int(100);内存a score | | ↓ ┌─────┐ │100 │ └─────┘现在Student ba;如果C默认复制相当于b.scorea.score;结果a.score | ↓ ┌─────┐ │100 │ └─────┘ ↑ | b.score两个对象共享同一块空间。五、灾难发生析构函数假设class Student { public: int *score; ~Student() { delete score; } };程序结束对象销毁。先销毁b执行delete b.score;100被释放。然后销毁a。执行delete a.score;可是a.score也指向刚才那块。问题同一块内存被释放两次。这就是内存错误六、怎么办我们需要告诉C复制对象的时候不要复制地址。我要复制里面的数据。这就是拷贝构造函数七、什么是拷贝构造函数简单理解当一个对象通过另一个对象创建时自动调用的特殊构造函数。形式类名(const 类名 变量) { }例如Student(const Student s) { }意思创建新学生时拿另一个学生作为模板。八、自己实现深拷贝完整代码#includeiostream using namespace std; class Student { public: int *score; //普通构造函数 Student() { scorenew int(100); } //拷贝构造函数 Student(const Student s) { scorenew int(*s.score); } //析构函数 ~Student() { delete score; } }; int main() { Student a; Student ba; }关键scorenew int(*s.score);拆开看第一步*s.score取值100第二步new int(100)重新创建新的100结果a.score | ↓ ┌─────┐ │100 │ └─────┘ b.score | ↓ ┌─────┐ │100 │ └─────┘两个对象完全独立。九、拷贝构造函数什么时候自动调用主要有3种情况。情况1对象初始化Student a; Student ba;调用Student(const Student s)情况2函数参数传对象例如void fun(Student s) { }调用fun(a);这里会复制a → s调用拷贝构造函数。情况3函数返回对象例如Student getStudent() { Student s; return s; }返回时可能需要复制。十、那么为什么还需要析构函数因为谁申请谁负责释放。例如scorenew int(100);申请内存。以后必须delete score;否则内存泄漏。所以如果类管理资源必须考虑三个问题。十一、Rule of Three三法则C里面有一个经典原则如果一个类需要自己写其中一个通常也需要自己写另外两个。这三个是1. 析构函数负责释放资源。例如~Student() { delete score; }2. 拷贝构造函数负责复制资源。例如Student(const Student s) { scorenew int(*s.score); }3. 拷贝赋值运算符负责两个已经存在的对象之间复制。例如ab;注意这个和Student ab;不一样十二、拷贝构造 vs 赋值运算符很多学生容易混。第一种创建新对象Student ba;调用拷贝构造函数第二种已有对象Student a; Student b; ba;调用赋值运算符图Student ba; 创建 ↓ 拷贝构造 ---------------- ba; 已经存在 ↓ operator十三、三法则完整结构一个负责动态内存的类通常class Student { public: int *score; //构造 Student() { scorenew int(100); } //拷贝构造 Student(const Student s) { scorenew int(*s.score); } //赋值运算符 Student operator(const Student s) { if(this!s) { delete score; scorenew int(*s.score); } return *this; } //析构 ~Student() { delete score; } };十四、给同学们的故事总结假设你的书包里有一本秘密笔记。普通复制只写笔记在哪里这是浅拷贝。深度复制重新抄一本新的笔记这是深拷贝。C为什么需要拷贝构造因为C不知道你的指针里面装的是“地址”还是“真正的东西”。所以你需要告诉它复制时应该怎么办。十五、信奥学生应该掌握到什么程度对于GESP/CSP-J阶段重点理解✅ 什么是对象复制✅ 什么情况下调用拷贝构造✅ 浅拷贝导致的问题✅ 深拷贝解决问题✅ 三法则概念暂时不用大量手写operator移动构造函数move语义但是如果以后学习链表智能指针STL底层实现这些知识会非常重要。最后送给同学们一句口诀对象复制有魔法 普通成员直接拿。 遇到指针要小心 复制地址会出错。 拷贝构造来帮忙 深拷贝才安全。 申请资源自己管 三大函数记心间。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价