C++浅拷贝和深拷贝

文章讨论了C++中的浅拷贝和深拷贝概念,指出在对象复制时两者内存操作的不同。浅拷贝适用于数据成员为基本类型的情况,而当数据成员包含指针时,浅拷贝可能导致指针悬挂问题,此时需要深拷贝以避免这个问题。文中通过示例代码展示了深拷贝如何在堆内存中创建新的空间来复制指针数据,确保对象独立性。
摘要由CSDN通过智能技术生成

浅拷贝和深拷贝是两种常用的对象复制方式,区别在于拷贝对象是所进行的内存操作不同

在没用定义拷贝构造函数的情况下,系统会调用默认的拷贝构造函数--就是浅拷贝,这个是可以不用自己定义的,它可以完成简单的值的拷贝--复制.数据成员中没有指针时,浅拷贝方式是可行的;并且被拷贝的对象中成员变量的值发生变化不会影响原来对象中的成员变量的值,如:

#include<iostream>
using namespace std;

class Test
{
public:
	Test(int a) :m_a(a) {};
	//这是编译器为我们提供的默认的拷贝构造函数形式,不写也可以
	Test(const Test& test)
	{
		this->m_a = test.m_a;
	}
	int m_a;
};

int main()
{
	Test obj1(5);
	Test obj2(obj1);
	cout << "obj1=" << obj1.m_a << endl;//obj1.m_a=5;
	cout << "obj2=" << obj2.m_a << endl;//obj2.m_a=5;
	cout << "&obj1=" << &obj1 << endl;//&obj1=0000008862F3F9E4
	cout << "&obj2=" << &obj2 << endl;//&obj1=0000008862F3F9E4
	obj1.m_a = 10;
	cout << "obj1=" << obj1.m_a << endl;//obj1.m_a=10;
	cout << "obj2=" << obj2.m_a << endl;//obj2.m_a=5;
	obj2.m_a = 10;
	cout << "obj1=" << obj1.m_a << endl;//obj1.m_a=10;
	cout << "obj2=" << obj2.m_a << endl; //obj2.m_a=10;
	return 0;
}

上面的代码就成功说明了如果数据是基本类型(int,double..),那么对浅拷贝后的其中一个变量进行修改不会影响原来数据的值,两个变量所占用的内存在物理上已近分开.

但是,如果在浅拷贝中,数据成员拥有指针时,拷贝后两个指针会指向同一块内存(同一块地址/同一个堆区),当对象快结束时,会调用两次析构函数,对这个内存释放两次,就会导致指针悬挂,如:

class Person {
public:
    int age;
    int* ptr;
    Person(int a, int p) : age(a), ptr(new int(p)) {}
    ~Person() {
        delete ptr;
    }
};

int main() {
    Person p1(18, 100);
    Person p2 = p1; // 拷贝构造函数
    std::cout << *(p1.ptr) << " " << *(p2.ptr) << endl;  // 输出:100 100
    *(p1.ptr) = 200;
    cout << *(p1.ptr) << " " << *(p2.ptr) << endl;  // 输出:200 200
    delete p1.ptr;
    cout << *(p2.ptr) << endl;  // 此处已经释放内存,输出未定义
    return 0;
}

因此,必须使用深拷贝,深拷贝与浅拷贝的区别就在于深拷贝会在堆内存中另外申请空间来储存数据(新的堆区空间进行拷贝),从而也就解决了指针悬挂的问题。简而言之,当数据成员中有指针时,必须要用深拷贝。如:

class Person
{
public:
	Person()
	{
		cout << "Person的默认构造函数" << endl;
	}
	Person(int age,int height)
	{
		m_Age = age;
		m_Height = new int(height);
		cout << "Person的有参构造函数" << endl;

	}
	Person(const Person& p)
	{
		this->m_Age = p.m_Age;
		//this->m_Height = p.m_Height;
		this->m_Height = new int(*p.m_Height);//在堆区上重新开辟一块内存空间
		cout << "Person的拷贝构造函数" << endl;
	}
	~Person()
	{
		if (m_Height != NULL)
		{
			delete m_Height;
		}
		cout << "Person的析构函数调用" << endl;
	}

	int m_Age;
	int* m_Height;
};

void test()
{
	Person p1(21, 163);
	cout << "p1的年龄:" << p1.m_Age << "p1身高:" << *p1.m_Height << endl;
	Person p2(p1);
	cout << "p2的年龄:" << p2.m_Age << "p2身高:" << *p2.m_Height << endl;
}
int main()
{
	test();
	return 0;
}

结果:成功运行

Person的有参构造函数
p1的年龄:21p1身高:163
Person的拷贝构造函数
p2的年龄:21p2身高:163
Person的析构函数调用
Person的析构函数调用

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值