【C++指南】类和对象(四):类的默认成员函数——全面剖析 : 拷贝构造函数

embedded/2024/10/23 0:53:14/

 引言

拷贝构造函数是C++中一个重要的特性,它允许一个对象通过另一个已创建好的同类型对象来初始化

了解拷贝构造函数的概念、作用、特点、规则、默认行为以及如何自定义实现,对于编写健壮和高效的C++程序至关重要。

 C++类和对象系列文章,可点击下方链接阅读:

【C++指南】类和对象(一):类和对象的定义和使用 基础讲解_c++ 类对象的使用-CSDN博客

【C++指南】类和对象(二):类的默认成员函数——全面剖析 :构造函数-CSDN博客

【C++指南】类和对象(三):类的默认成员函数——全面剖析: 析构函数-CSDN博客

【C++指南】类和对象(四):类的默认成员函数——全面剖析 拷贝构造函数-CSDN博客

【C++指南】类和对象(五):类的默认成员函数——全面剖析 赋值运算符重载函数-CSDN博客

目录

引言

🍃概念

🍃作用

🍃特点

触发拷贝函数自动调用的情况:

🍃规则

🍃默认拷贝构造函数的行为

🍃自定义实现拷贝构造函数

🍃总结


🍃概念

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

拷贝构造函数是一种特殊的构造函数,它接受一个同类型的对象的引用作为参数,用于初始化新创建的对象。

拷贝构造函数的声明通常如下:

ClassName(const ClassName& other);
其中,ClassName是类的名字,other 是传入的对象。 

🍃作用

拷贝构造函数的主要作用是实现对象的深拷贝或浅拷贝

  • 深拷贝:在内存中为对象分配新的空间,并复制源对象的所有成员(包括动态分配的内存)。
  • 浅拷贝:仅复制对象的成员值,如果成员包含指针,则两个对象将共享相同的内存地址。

关于浅拷贝与深拷贝的详细内容可以参考文章:

【C++指南】C++中的浅拷贝与深拷贝:深入剖析-CSDN博客 

🍃特点

  • 自动调用:在对象通过另一个对象初始化时,拷贝构造函数会被自动调用。
  • 参数传递:拷贝构造函数的参数是常量引用(const ClassName&),避免不必要的拷贝,同时防止对象在拷贝过程中被修改。

拷贝构造函数的参数必须是类类型对象的引用,而不是传值方式。主要是因为:

避免无限递归

如果拷贝构造函数的参数是传值方式,那么在调用拷贝构造函数时,编译器会尝试创建一个临时对象来传递给该函数。这个临时对象的创建又会调用拷贝构造函数,从而导致无限递归。最终,这会导致栈溢出和编译错误。

触发拷贝函数自动调用的情况:

1.对象初始化

  • 使用另一个同类型的对象来初始化一个新对象时。
MyClass obj1;  
MyClass obj2 = obj1;  // 调用拷贝构造函数

 2.函数参数传递

  • 当一个对象作为值参数传递给函数时。
void func(MyClass obj) {  // 在这里,obj是通过拷贝构造函数创建的  
}  
MyClass obj1;  
func(obj1);  // 调用拷贝构造函数

3.函数返回值

  • 当一个函数返回一个对象(作为值)时,会调用拷贝构造函数来构造返回的对象。
MyClass func() {  MyClass obj;  return obj;  // 调用拷贝构造函数  
}

4.编译器生成的临时对象

  • 编译器在某些情况下会生成临时对象,例如,在表达式中计算中间结果时。
MyClass obj = MyClass();  // 这里的`MyClass()`创建了一个临时对象,然后调用拷贝构造函数赋值给obj

🍃规则

  • 如果类中没有显式定义拷贝构造函数,编译器会提供一个默认的拷贝构造函数。
  • 拷贝构造函数不能被声明为const,因为它需要修改(初始化)目标对象。
  • 拷贝构造函数必须是可访问的,以便在需要时能够被调用。

🍃默认拷贝构造函数的行为

默认拷贝构造函数的行为是逐成员复制,对于基本类型成员,直接复制值,也就是浅拷贝对于对象成员,调用其拷贝构造函数

这种默认行为通常适用于不包含动态分配内存或资源管理(如文件句柄、网络连接等)的简单类。

🍃自定义实现拷贝构造函数

当类包含动态分配的内存、指针或需要管理的资源时,必须自定义拷贝构造函数来实现深拷贝,以避免浅拷贝带来的问题(如重复释放内存、数据不一致等)。

Tips:

如果⼀个类显式实现了析构并释放资源,那么他就 需要显式写拷贝构造,否则就不需要

以下是一个包含动态分配内存的类的示例,展示如何自定义拷贝构造函数:

#include <iostream>  
#include <cstring>  class MyClass {  
private:  char* data;  public:  // 默认构造函数  MyClass(const char* str = "") {  data = new char[strlen(str) + 1];  strcpy(data, str);  }  // 拷贝构造函数  MyClass(const MyClass& other) {  data = new char[strlen(other.data) + 1];  strcpy(data, other.data);  }  // 析构函数  ~MyClass() {  delete[] data;  }  // 打印数据  void print() const {  std::cout << data << std::endl;  }  
};  int main() {  MyClass obj1("Hello");  MyClass obj2 = obj1; // 调用拷贝构造函数  obj1.print(); // 输出: Hello  obj2.print(); // 输出: Hello  return 0;  
}
在这个例子中,MyClass 包含一个指向字符数组的指针。自定义拷贝构造函数通过分配新的内存并复制字符串内容,实现了深拷贝。析构函数负责释放动态分配的内存,防止内存泄漏。

🍃总结

  • 拷贝构造函数是C++中用于通过另一个对象初始化新对象的特殊构造函数。
  • 它接受一个同类型的常量引用作为参数。
  • 如果没有显式定义,编译器会提供一个默认的拷贝构造函数,逐成员复制对象。
  • 自定义拷贝构造函数通常用于实现深拷贝,以避免浅拷贝带来的问题。
  • 编写拷贝构造函数时,需要特别注意动态分配的内存和需要管理的资源,确保正确复制和释放。

通过理解和应用拷贝构造函数,可以编写出更加健壮和高效的C++程序。

 


http://www.ppmy.cn/embedded/129697.html

相关文章

代码随想录算法训练营第51天|101. 孤岛的总面积、102. 沉没孤岛、103. 水流问题、104.建造最大岛屿

文章目录 101. 孤岛的总面积102. 沉没孤岛103. 水流问题104.建造最大岛屿 101. 孤岛的总面积 卡码网 101. 孤岛的总面积 代码随想录 from collections import deque n, m map(int, input().split())matrix []for i in range(n):matrix.append(list(map(int, input().split(…

web网页QQ登录

代码&#xff1a; <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>QQ登录ent</title> </head> <style>ul > li{list-style: none; } a …

【React】useLayoutEffect、useInsertionEffect

useLayoutEffect useLayoutEffect和useEffect有什么区别呢&#xff1f; useEffect的cb&#xff0c;准确来说&#xff0c;是异步调用的&#xff0c;会等主线程任务执行完成&#xff0c;D0M更新&#xff0c;JS执行完成&#xff0c;视图绘制完成&#xff0c;才执行。 useLayout…

<a-table>行数据增加点击事件并获取点击行的数据+自定义button按事件

先看代码&#xff1a; 在 Ant - Design - Vue 的<a - table>组件中&#xff0c;通过customRow属性可以为表格的每一行添加自定义的行为和样式。当设置customRow为一个返回包含onClick函数的对象的函数时&#xff0c;实际上是在为每一行添加一个点击事件监听器。 在a-tabl…

应用层协议编写,序列化反序列化,网络版计算器,Json序列反序列化工具,条件编译,结合网络协议栈理解协议定制

我们前面说了tcp与udp传输层协议的使用&#xff0c;现在我们来看看传输层的上层应用层&#xff0c;我们是如何约定协议的&#xff0c;是如何让我们的数据封装的&#xff1b; 1.应用层协议 为什么会有应用层协议呢&#xff1f;我们在前面tcp和udp服务器客户端代码实现时就已经…

vnc+wsl2试用

vncwsl2试用 一、vnc VNC&#xff08;Virtual Network Computing&#xff09;是一种远程桌面共享技术&#xff0c;允许用户通过网络远程访问和控制另一台计算机的桌面界面。它基于客户端-服务器架构&#xff0c;主要用于在不同操作系统之间进行远程连接。 工作原理 客户端和…

数据脱敏方案总结

什么是数据脱敏 数据脱敏的定义 数据脱敏百度百科中是这样定义的&#xff1a; 数据脱敏&#xff0c;指对某些敏感信息通过脱敏规则进行数据的变形&#xff0c;实现敏感隐私数据的可靠保护。这样就可以在开发、测试和其它非生产环境以及外包环境中安全地使用脱敏后的真实数据集…

.net framework 3.5sp1安装错误卡住不动怎么解决

解决 .NET Framework 3.5 SP1 安装错误卡住的问题&#xff0c;可以尝试以下几种方法&#xff1a; 1.使用 DISM 工具&#xff1a; 将下载的 NetFx3.cab 文件放置在 C:\Windows 文件夹下。 以管理员身份打开命令提示符&#xff0c;输入以下命令&#xff1a; dism /online /En…