C++中的深拷贝与浅拷贝

本文介绍了C++中深拷贝和浅拷贝的概念,通过实例展示了两者区别。深拷贝创建了对象的新副本,而浅拷贝只是创建了对象的别名。文章详细讨论了深拷贝在String类中的应用,特别是构造函数、拷贝构造函数、拷贝赋值函数和析构函数中的实现,并强调了不正确使用浅拷贝可能导致的内存泄漏问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 概念

在C++涉及指针的部分中,有 深拷贝浅拷贝 两个概念,让我们通过例子来理解一下。C++中,字符串是通过首地址来表示的,如图所示:

字符串

图中,字符串用 s1 表示,而 s1 是字符串 “HELLO” 的首地址(字符串以 ‘\0’ 作为结束标志),通过寻址,即可实现字符串操作。下图中创建了一个字符串 s2 ,上面的表示 深拷贝 ,下面的表示 浅拷贝

拷贝

由上图可以看出,深拷贝又创建了一份新的字符串副本, s2 就是字符串副本的首地址,而浅拷贝仅仅是给 s1 起了一个别名 s2 。那么,这两种拷贝方式有什么需要注意的呢?

1.因为 s1s2 指向同一块内存区域,所以,如果 s1 指向的内容发生改变,那么 s2 指向的内容随之改变。
2.如果 s2 原来指向一块内存,在没有释放 s2 指向的内存的情况下就把 s1 浅拷贝给 s2 ,那么 s2 原来指向的空间就发生了内存泄漏,造成程序无法将这块内存还给计算机。(因为此时没有指针指向这块区域)

2. 实际应用

在C++中,有一个 String 类,内部就涉及到了深拷贝和浅拷贝。程序(下面程序块和 String 源码类似)如下:

class String{
public:
	String(const char* cstr = 0);  //构造函数
	String(const String& str);     //拷贝构造函数
	String& operator= (const String& str);  //拷贝赋值函数
	~String();  //析构函数
	char* get_c_char() const { return m_data; }
private:
	char* m_data;
};

上面的函数分别是 构造函数拷贝构造函数拷贝赋值函数析构函数
构造函数拷贝构造函数 的不同之处在于其参数的区别,拷贝构造函数 的参数是自身类型的对象。下面就每个函数分别介绍。

2.1 构造函数

inline String::String(const char* cstr = 0){
	if (cstr){
		m_data = new char[strlen(cstr) + 1];  //+1 为了存储'\0'
		strcpy(m_data, cstr);
	}
	else{
		m_data = new char[1];
		*m_data = '\0';
	}
}

2.2 拷贝构造函数

inline String::String(const String& str){
	m_data = new char[strlen(str.m_data) + 1];
	strcpy(m_data, str.m_data);
}

2.3 拷贝赋值函数

inline String& String::operator=(const String& str){
	if (this == &str){  //检测是否是自身赋值
		return *this;
	}
	delete[] m_data;
	m_data = new char[strlen(str.m_data) + 1];
	strcpy(m_data, str.m_data);
	return *this;
}

这里用的就是 深拷贝 ,如果直接使用 浅拷贝 ,会导致 str 原来指向的内存没有指针所指,即发生了内存泄漏。(C++默认的是 浅拷贝 )此外,与上面的两个构造函数不同,拷贝复制函数的对象本身已经存在,所以为了避免对自身赋值造成错误,加入了判断条件。
注:不加判断的话,对自身赋值会错误,因为 delete 了原来字符数组的内容,后面的拷贝操作 strcpy 会失败。

2.4 析构函数

inline String::~String(){
	delete[] m_data;
}

由于构造函数中都采用了 new 运算符动态创建字符数组的方式,所以在析构函数中要 delete 掉内存。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九霄星河

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值