首页 > 其他分享 >关于浅拷贝和深拷贝中需要注意的点

关于浅拷贝和深拷贝中需要注意的点

时间:2024-05-18 16:21:31浏览次数:13  
标签:返回 arr pAddress MyArry 对象 注意 拷贝 关于

-拷贝函数的调用时机

// 1.直接以创建好的对象初始化
Person p1(20);
Person p2(p1);
// 2.以值传递的方式
Person p;
doWork(p);
// 3.以值方式返回局部变量
Person p1;
return p1;// 局部变量,并不是返回上一行的p1,而是拷贝一个返回

-情况:当成员中需要在堆上申请空间时。当构造对象时把对象当成参数传入的时候,在没有自己编写深拷贝构造函数,编译器会自动调用浅拷贝函数。浅拷贝就是直接把传入参数的成员一一对应的赋值给构造对象,当成员不是堆上的数据时,这样子没有问题。但是当某个成员属性是在堆上的数据,那么编译器只会把传入对象的成员的指向复制给构造对象的成员。这样子传入对象和构造对象就有某个成员属性指向堆上的同一块内存。总所皆知类中如果有堆上申请的成员,那么在析构函数中则必须自己去释放。这个时候由于传入对象和构造对象都有属性指向堆上同一个内存。那么当程序执行完后,执行析构函数时,会按照先进后出的顺序执行析构函数,就会出现重复释放的问题。

  • 解决:自己编写深拷贝函数,防止出现浅拷贝。
//自己的的通用的数组类
#pragma once
#include<iostream>
using namespace std;

template<class T>
class MyArry {
private:
	//指向堆区开辟的数组
	T* pAddress;

public:
	MyArry(int capacity) {
		cout << "有参构造函数调用" << endl;
		this->pAddress = new T[this->mCapacity];
	}
	~MyArry() {
		if (this->pAddress) {
			cout << "析构函数的调用" << endl;
			delete[] this->pAddress;
			this->pAddress = NULL;
		}
	}
	//拷贝构造
	MyArry(const MyArry& arr) {
		this->pAddress = new T[arr.mCapacity];

		//复制数据过来
		for (int i = 0; i < arr.mSize; i++) {
			this->pAddress[i] = arr.pAddress[i];
		}
	}

	//operator= 防止浅拷贝
	// 使用=构造的前提必须是=左边的对象是已经存在的对象
	//为什么返回的是一个引用而不是指针
	/*
		1.返回局部对象的指针是一个很危险的操作。当函数返回时候
		,局部对象会被销毁。那么就会得到一个悬空指针。
		2.返回引用是一贯用法。
		3.防止浅拷贝,并且允许链式赋值a=b=c,因为c++中=是返回引用
	*/
	MyArry& operator=(const MyArry& arr) {
		//先判断原来堆区是否有数据
		//有自己原来有数据,先释放,再拷贝
		if (this->pAddress) {
			delete[] this->pAddress;
			this->pAddress = NULL;
		}
		this->pAddress = new T[arr.mCapacity];
		//复制数据过来
		for (int i = 0; i < arr.mSize; i++) {
			this->pAddress[i] = arr.pAddress[i];
		}
		//这里返回*this,表示是返回this的指针,而不是对象的地址
		//允许链式赋值
		//返回指针this是错误的,因为函数的返回值要求返回一个引用,而引用和指针是两种类型
		return *this;
	}
};

标签:返回,arr,pAddress,MyArry,对象,注意,拷贝,关于
From: https://www.cnblogs.com/wzy-cc/p/18199419

相关文章

  • 关于cmd运行javac提示'javac' 不是内部或外部命令,也不是可运行的程序的问题
     大家可以看到我这边cmd运行javac命令,它对我进行了错误的提示,提示javac不是可运行命令和程序。这个问题的根本在于环境变量的配置出现了错误。接下来就要进行jdk的环境配置了。  注意点:这里要定位到自身存放jdk的bin目录才会生效。  点击确定即可,然后打开cmd窗口......
  • 项目管理案例-关于第三方公司提供的组件质量欠佳的问题
    项目管理案例-关于第三方公司提供的组件质量欠佳的问题背景     商用密码应用安全性评估(简称密评),是指按照有关法律法规和标准规范,对网络与信息系统使用商用密码技术、产品和服务的合规性、正确性、有效性进行检测分析和评估验证的活动。依据《密码法》、《商用密码管理条例......
  • 测试阶段注意事项
    一.用例设计阶段  01.需求多与产品交流,把需求搞清楚  02. 涉及数据或接口被外部系统调用需求评审,需求评审时,需要与产品、研发确认是否会影响其他系统。  03.涉及数据刷新类的需求,需与产研交流确认数据刷新存在问题和影响范围  04.需要分析下研发提供的影......
  • 关于华为eNSP模拟器的端口占用问题
    一、关闭虚拟化:按下WIN+R输入cmd,按ctrl+shift+enter以管理员身份运行命令提示符输入以下代码:bcdedit/sethypervisorlaunchtypeoff回车执行二、关闭Hyper-V和虚拟机平台:打开控制面板->程序->启用或关闭windows功能把Hyper-V和虚拟机平台关闭重启电脑......
  • 关于前后端项目分离开发的一些思考
    开发模式前后端分离开发前端使用vue或其他的一些前端框架进行页面开发,进行打包为html文件后端使用SpringBoot开发后,进行打包也就是分离开发,分开打包部署方式分开部署前端代码结合Nginx进行部署,Nginx将请求转发到后端服务器中;结合部署这种个人认为是单机部署的一种方式,......
  • 关于IDEA使用xml实现动态sql的问题
     如上图,我在mapper层编写了一个list方法用于实现动态sql。1.导入使用xml文件的mybatis依赖。 2.配置文件的修改.properties .yml mybatis.mapper-locations=classpath:mapper/*.xml:这个配置项指定了MyBatis映射器XML文件的位置。值classpath:mapper/*.xml......
  • 关于git使用git push -u origin 命令时,出现的错误的问题。
    出现这个错误原因,其实就是没有正确执行指令造成的,也就是没有正常提交数据。gitadd.#添加当前目录下的所有文件到暂存区:gitcommit-m"test"#提交暂存区文件到仓库,-m表示可以直接输入的内容为的testgitpush-uoriginmaster带上-u 参数其实就相当于记录了push到远端分......
  • 关于SpringBoot项目使用Hutool工具进行json序列化时出现Null值过滤或者丢失的问题(转
    ##问题描述:SpringBoot项目中,一直使用的时Hutool的json转换工具,被强制要求不能使用fastJson工具;之前都没什么问题,突然有一次使用parseObj()进行json字符串转换json对象时,突然报错:Noserializerfoundforclasscn.hutool.json.JSONNullandnopropertiesdiscoveredtocreate......
  • 【自用】各类非编程类工具使用注意事项
    截图:FastStoneCapture截图保存时设置不压缩、256位彩色,比Snipaste及系统PrtSc截图保存的文件要大。drawio:drawio导出svg时嵌入字体会变糊。drawio画图在A4页面占比不能太大,否则导出为svg后再插入word会变得很模糊。文本格式化如果不勾选,则只能设置一种字体。组织架构图,要用正......
  • 关于“error: Microsoft Visual C++ 14.0 is required. Get it with "Build Tools for
    安装库之前一定要注意python版本,今天鬼迷日眼的装一堆堆库,一个回车冒出来这个鬼问题。百度无果后灵光乍现,只安装报错时对应的库:condainstallnumpy==1.20.1结果在输出里找出这一段:Specifications:-numpy==1.20.1->python[version='>=3.7,<3.8.0a0|>=3.8,<3.9.0a0|>=......