栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

<C++>深浅拷贝与初始化列表技巧你真的会了吗

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

<C++>深浅拷贝与初始化列表技巧你真的会了吗

清欢无别事,我在等风也等你

前言

C++对象特性里的拷贝构造函数有更深入的含义,而且面试曾经问过关于拷贝的析构问题,那么今天就好好解析一下深浅拷贝的问题;还有初始化列表的形式,这个在给对象属性初始化的时候非常方便,建议大家熟练掌握,话不多说,开始正文。


目录

深浅拷贝区别

代码解释

特别注意

内存图解释

初始化列表

语法

具体实现

总结


深浅拷贝区别

上一节简单提了编译器会默认给我们提供值拷贝构造函数,结果是新的对象会拥有和传入对象一样的属性,由编译器提供的拷贝构造被称为浅拷贝构造,而由我们自己编写的不同于编译器提供的拷贝构造函数就叫深拷贝构造了,举个典型的例子说明。

代码解释
#include
using namespace std;
//深浅拷贝问题,存在经典的坑,面试考过
class Person
{
public:
	Person(int age,int height)
	{
		m_age = age;
		m_Height = new int(height);
		cout << "Person 的有参构造函数调用" << endl;
	}
	//自己写不同于编译器的拷贝构造函数属于深拷贝
	Person(const Person& p)
	{
		cout << "拷贝构造函数调用" << endl;
		m_age = p.m_age;
		//m_Height = p.m_Height;
		
		m_Height =new int(*p.m_Height);
	}
	~Person()
	{
		//析构代码,将堆区开辟的数据做释放操作
		if (m_Height != NULL)
		{
			delete m_Height;
			m_Height = NULL;
		}
		cout << "~Person 的析构构造函数调用"< 

创建Person类,设置m_age和指针类型*m_Height为私有属性;依次对Person类设置有参构造和拷贝构造函数以及析构函数;前面析构函数一直没有什么作用,其实它是用来清理对象的,析构函数会在程序结束前自动调用,这时候就可以使用delete清理掉;

特别注意
Person(const Person& p)
	{
		cout << "拷贝构造函数调用" << endl;
		m_age = p.m_age;
		//m_Height = p.m_Height;
		
		m_Height =new int(*p.m_Height);
	}
	~Person()
	{
		//析构代码,将堆区开辟的数据做释放操作
		if (m_Height != NULL)
		{
			delete m_Height;
			m_Height = NULL;
		}
		cout << "~Person 的析构构造函数调用"< 

这里不能使用编译器提供的浅拷贝,如果直接使用m_Height=p.m_Height,毫无疑问这两个属性地址相同,那么在调用析构函数的时候,p1先释放内存,这时候虽然有一个NULL判断,但是此块内存已经被删除,再次访问都会提示错误,这是很危险的,所以我们需要用深拷贝解决重复删除的问题。使用m_Height=new int(*p.m_Height) 语句给身高属性重新开辟空间,这样在调用析构的时候各自清理各自的属性,就解决了这个浅拷贝带来的重复清理问题。

内存图解释

上面是浅拷贝的p1、p2对象的内存示意图,两次析构会重复当问0x00011地址,但是当这个地址被删除后,是不允许再次访问的。

利用我们设置的深拷贝构造后,地址不一样,各自删除各自的地址,解决问题

初始化列表

初始化列表用来给属性初始化

语法

普通构造函数+ : + 类属性(变量或常量)+ {}

具体实现
class Person
{
public:
	Person() :m_age(20), m_sex(1), m_height(180){}
	Person(int a, int b, int c) :m_age(a), m_sex(b), m_height(c){}
	int m_age;
	int m_sex;
	int m_height;
};
int main()
{
	Person p1;
	Person p2(10, 20, 30);
	cout << "年龄为:" << p1.m_age;
	cout << "性别为:" << p1.m_sex;
	cout << "身高为:" << p1.m_height< 

主函数中p1调用无参构造函数,各属性初始化为属性()括号里面的值;p2调用有参构造函数,将实参10,20,30分别传给a,b,c,然后a的值传给m_age,b的值传给m_sex;c的值传给m_height;直接来看结果:

总结

C++对象特性的深浅拷贝和初始化列表到这里就分享完了,那麽意味着对象的初始化和清理就结束了,到后面会讲一下静态成员和类对象作为类成员的一个案例,用于巩固这部分知识点,希望下篇文章也可以得到你们的青睐,下次再见!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/923022.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号