拷贝构造(深拷贝、浅拷贝)

article/2025/9/17 4:26:59

一、概念介绍

拷贝构造:拷贝构造函数,又称构造函数,是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构造及初始化。

其唯一的形参必须是引用,但并不限制为const,一般普遍的会加上const限制。

在类中如果没有显式给出拷贝构造函数时,则C++编译器自动给出一个缺省的拷贝构造函数。

浅拷贝:浅拷贝就是对象的数据成员之间的简单赋值。

c++默认的拷贝构造函数是浅拷贝,如你设计了一个没有类而没有提供它的拷贝构造函数,当用该类的一个对象去给令一个对象赋值时所执行的过程就是浅拷贝,如:

class a {
public:int size;
public:a(int size) : size(size) {}
};int main()
{a s(5), b = s;return 0;
}

b = s就是浅拷贝,执行完这条语句后,b.size = 5, 如果对象中没有其他的资源(如:堆,文件,系统资源等),则深拷贝和浅拷贝没有什么区别。
但当对象中有指针等变量的时候,比如:

class a {
public:int size;int* data;
public:a(int size) : size(size) {data = new int[size];}~a() {delete data;data = nullptr;}
};int main()
{a s(5), b = s;return 0;
}

这个时候再执行代码就会报错,因为浅拷贝只是单纯的让

b.size = s.size

b.data = s.data

这时b和s中的data指向同一块堆内存,在b和s的执行析构函数时,对同一块内存进行了两次释放(指针悬挂),这样的结果是未定义的,会导致内存泄漏或者程序崩溃。

这时,我们需要用到深拷贝来解决这个问题。

深拷贝:当拷贝对象中有对其他资源(如堆、文件、系统等)的引用时(引用可以是指针或引用),对象会另开辟一块新的资源,而不再对拷贝对象中有对其他资源的引用的指针或引用进行单纯的赋值。

class a {
public:int size;int* data;
public:a(int size) : size(size) {data = new int[size];}a(const a& as) : size(as.size) {data = new int[size];}~a() {delete data;data = nullptr;}
};int main()
{a s(5), b = s;return 0;
}

这样在进行b=s赋值之后就不会出现同一块内存二次释放的错误了。 

1.调用拷贝构造的情形

①当对象作为函数参数时

void fun(aa a)
{cout << "fun" << endl;
}int main()
{aa a;fun(a);return 0;
}

②当对象作为函数返回值时

aa pfun()
{aa b;return b;
}int main()
{aa a;pfun();return 0;
}

 

③当用一个对象初始化另一个对象时

class aa {
public:aa() {cout << "construct" << endl;}aa(const aa& as) {cout << "copy" << endl;}
};int main()
{aa a(5);aa b(a), c = a;return 0;
}

上面两条语句均会执行拷贝构造。

 但是这句话不会执行拷贝构造,只是赋值。

class aa {
public:aa() {cout << "construct" << endl;}aa(const aa& as) {cout << "copy" << endl;}
};int main()
{aa a,b;b = a;return 0;
}

 

二、注意事项

1.深拷贝和浅拷贝的区别:

浅拷贝会把指针变量的地址复制; 深拷贝会重新开辟内存空间。

2.当数据成员中有指针时,必须要用深拷贝。

3.拷贝构造的参数必须是对象的引用,const条件不是严格必须的,但是加上最好。

为什么一定要是引用呢?

如果拷贝构造函数中的参数不是一个引用,即形如CClass(const CClass c_class),那么就相当于采用了传值的方式(pass-by-value),而传值的方式会调用该类的拷贝构造函数,从而造成无穷递归地调用拷贝构造函数。因此拷贝构造函数的参数必须是一个引用。

注意:不是为了减少一次内存拷贝,而是为了防止无限制的内存拷贝!!!


http://chatgpt.dhexx.cn/article/BgMXJWTn.shtml

相关文章

C++——深拷贝和浅拷贝

1.浅拷贝与深拷贝的区别 浅拷贝&#xff08;默认拷贝函数&#xff09;&#xff1a;将原对象或原数组的引用直接赋给新对象&#xff0c;新数组&#xff0c;新对象/新数组只是原对象的一个引用。 深拷贝&#xff1a;创建一个新的对象和数组&#xff0c;将原对象的各项属性的“值”…

深拷贝和浅拷贝的区别和与原理

一、基本类型和引用类型 string,number,boolean,null,undefined,symbolFunction,Array,Object 基本类型是按值访问的&#xff0c;引用类型是按引用访问 基本类型和引用类型也有人叫原始类型和对象类型&#xff0c;拥有方法的类型和不能拥有方法的类型&#xff0c;可变类型和不…

浅拷贝、深拷贝

深拷贝和浅拷贝 这两个概念是在项目中比较常见的&#xff0c;在很多时候&#xff0c;都会遇到拷贝的问题&#xff0c;我们总是需要将一个对象赋值到另一个对象上&#xff0c;但可能会在改变新赋值对象的时候&#xff0c;忽略掉我是否之后还需要用到原来的对象&#xff0c;那么就…

深拷贝和浅拷贝(copy和deepcopy)详解

深拷贝和浅拷贝&#xff08;copy和deepcopy&#xff09;详解 详细解释存储方式列表的增删改列表修改已有值列表新增一个值列表整体重新赋值 copy与deepcopy的区别不可变类型可变类型 浅拷贝指的是创建一个新对象&#xff0c;其中包含原始对象的引用&#xff08;指针&#xff09…

浅拷贝和深拷贝的区别?

创建Java对象的方式包括new、反射、反序列化、拷贝&#xff0c;那么什么是拷贝呢&#xff1f;浅拷贝和深拷贝又有什么区别呢&#xff1f; 什么是拷贝 拷贝就是为了复用原对象的部分或全部数据&#xff0c;在原对象的基础上通过复制的方式创建一个新的对象。 Object类中有nati…

深拷贝和浅拷贝的区别

首先&#xff0c;明确一点深拷贝和浅拷贝是针对对象属性为对象的&#xff0c;因为基本数据类型在进行赋值操作时&#xff08;也就是拷贝&#xff09;是直接将值赋给了新的变量&#xff0c;也就是该变量是原变量的一个副本&#xff0c;这个时候你修改两者中的任何一个的值都不会…

浅拷贝与深拷贝的区别

浅拷贝与深拷贝 一、数据类型 数据分为基本数据类型(String, Number, Boolean, Null, Undefined&#xff0c;Symbol)和对象数据类型。 基本数据类型的特点&#xff1a;直接存储在栈(stack)中的数据 引用数据类型的特点&#xff1a;存储的是该对象在栈中引用&#xff0c;真实的…

堆、栈和队列

1. 堆 堆是在程序运行时&#xff0c;而不是在程序编译时&#xff0c;申请某个大小的内存空间。即动态分配内存&#xff0c;对其访问和对一般内存的访问没有区别。堆是指程序运行时申请的动态内存&#xff0c;而栈只是指一种使用堆的方法(即先进后出)。 2. 栈&#xff08;stack&…

堆、栈和队列的区别

目录 数据结构中的堆、栈和队列 内存申请中的堆和栈 一个C/C程序占用的内存如下&#xff1a; 申请内存后的响应 申请大小的限制 申请效率的比较 堆和栈中的存储内容 数据结构中的堆、栈和队列 堆&#xff1a;堆是一种经过排序的树形数据结构&#xff0c;每个结点都有…

栈和队列

文章目录 栈栈操作队列队列操作双端队列双端队列操作 栈 栈&#xff08;stack&#xff09;&#xff0c;有些地方称为堆栈&#xff0c;是一种容器&#xff0c;可存入数据元素、访问元素、删除元素&#xff0c;它的特点在于只能允许在容器的一端&#xff08;称为栈顶端指标&…

栈和队列简介

栈和队列简介 栈和队列是两种常用的数据结构&#xff0c;它们的数据是按线性结构存储的&#xff0c;因此&#xff0c;栈和队列也属于线性表。 栈和队列的数据可以存储在一个顺序表里&#xff0c;也可以存储在一个链表里&#xff0c;只要满足线性存储结构就行。只对数据的线性…

栈和队列基本操作

栈和队列 一、栈栈是什么栈的实现栈的基本操作栈类型的定义初始化栈检查栈是否为满入栈出栈获取栈顶元素检测栈是否为空测试函数 完整代码Stack.hStack.cmain.c 二、队列队列是什么队列的实现队列类型的定义申请一个节点初始化队列队尾入队列队头出队列获取队列头部元素获取队列…

C#队列和栈的使用

一、队列 队列是其元素以先进先出&#xff08;Firstin,Firstout,FIFO&#xff09;的方式来处理的集合。先放入队列中的元素会先读取。队列使用System.Collections.Generic命名空间中的泛型类Queue<T>实现。 队列的成员 Count&#xff1a;Count属性返回队列中元素个数。…

栈和队列经典面试题

目录 1、括号匹配问题 2、用队列实现栈 3、用栈实现队列 4、设计循环队列 1、括号匹配问题 链接直达&#xff1a; 有效的括号 题目&#xff1a; 思路&#xff1a; 做题前&#xff0c;得先明确解题方案是啥&#xff0c;此题用栈的思想去解决是较为方便的&#xff0c;栈明确指…

栈stack和队列

栈和队列 一 栈和队列二 栈三.队列 一 栈和队列 栈和队列是两种重要的线性结构。从数据结构来看&#xff0c;栈和队列也是线性表&#xff0c;其特殊性在于栈和队列的基本操作是线性表操作的子集&#xff08;也具有顺序结构和链式结构&#xff09;&#xff0c;它们是操作受限的…

链表,队列和栈的区别

链表&#xff0c;队列和栈都是数据结构的一种。Sartaj Sahni 在他的《数据结构、算法与应用》一书中称&#xff1a;“数据结构是数据对象&#xff0c;以及存在于该对象的实例和组成实例的数据元素之间的各种联系。这些联系可以通过定义相关的函数来给出。”他将数据对象&#x…

栈与队列的定义与区别

1、栈 首先&#xff0c;普通的线性表实现是有两个端口可以访问的&#xff0c;但是如果作为栈就要封闭一端&#xff0c;只能访问另一端。这当然不是自讨苦吃&#xff0c;栈是一种抽象数据结构&#xff0c;是对现实世界对象的模拟。比如&#xff0c;自助餐厅中的一叠盘子&#x…

java 队列和栈的区别

栈和队列的区别 &#xff08;1&#xff09;数据插入删除 栈是一种特殊的线性表&#xff0c;他只能在一段进行插入和删除操作&#xff0c;就好像是一个井一样。进行数据插入和删除就类似于井口&#xff0c;称为栈定。而井也是有底部的&#xff0c;栈无法进行插入删除操作的这一…

监督学习和无监督学习的区别(机器学习)

机器学习主要分为两类 监督学习无监督学习 两者的区别主要是是否需要人工参与数据结果的标注 监督学习&#xff1a;教计算机如何去完成预测任务&#xff08;有反馈&#xff09;&#xff0c;预先给一定数据量的输入和对应的结果即训练集&#xff0c;建模拟合&#xff0c;最后让…

简单说下有监督学习和无监督学习的区别

简单说下有监督学习和无监督学习的区别 解析&#xff1a; 有监督学习&#xff1a;对具有标记的训练样本进行学习&#xff0c;以尽可能对训练样本集外的数据进行分类预测。&#xff08;LR,SVM,BP,RF,GBDT&#xff09; 无监督学习&#xff1a;对未标记的样本进行训练学习&#xf…