C++::实现String类的浅拷贝形式

本文主要介绍并分析String类的浅拷贝形式.

(由于工程量较小,就不分文件了)

/*
*本代码版权归高小调博客所有 
*作者:最近头比较大,不知道怎么有效学习C++的高小调
*日期:2016-10-20
*代码功能:String类的浅拷贝形式  
*/
#include<iostream>
class String{
public:
	//构造函数,默认初始化为空串
	String(const char *pStr = ""){
		//防止String s(NULL);
		if(NULL != pStr){
			//pStr不为空时,开辟一段内存,并将源字符串拷贝过去
			_pStr = new char[strlen(pStr)+1];
			strcpy(_pStr,pStr);
		}else{
			//pStr为空时,开辟两个字节,创建空串
			//(多申请一个字节,方便析构的时候直接调用delete[]释放内存)
			_pStr = new char[1];
			*_pStr = '\0';
		}
	}
	~String(){
		delete[] _pStr;	
		_pStr = NULL;
	}
private:
	char *_pStr;
};
int main(){
	String s1("Hello");
	String s2(s1);
	return 0;
}

这样的程序,只要你敢运行,它就敢崩溃!

为什么我写这个String类会崩溃?我们来分析一下:

在这个String类中,因为没有显式的定义拷贝构造函数,因此编译器会默认合成一个.

编译器默认合成的拷贝构造函数,只是做简单地做赋值操作,把被拷贝对象内的各个成员,一一原封不动的赋值给了新对象的各个成员.

因此,拷贝构造函数调用完成之后,s1的pStr指针与s2的pStr指针,指向同一块内存区域.而这种以值拷贝的形式,我们称之为浅拷贝.

程序运行至此,一切正常,不足以崩溃.

而再接着向下走的时候,当mian函数内代码执行完之后,s1、s2对象即将被销毁,因此要调用析构函数.

因为栈"先入后出"的特性,决定了首先调用的是s2的析构函数,当s2析构函数调用完成之后,pStr指针所指向的内存就会被释放.

程序运行至此,也一切正常,不足以崩溃.

当程序继续接着向下走,析构s1对象时,因为s1的pStr指向的内存与s2的pStr指向的内存区域相同,而s2已经释放过了这块区域,因此当s1的析构函数再次调用delete[]尝试释放pStr指针所指向的内存区域时,异常发生了,程序崩溃了!

说了这么多,那么问题来了:C++中的String类到底该怎么写?

posted @ 2016-10-21 14:34  站长高小调  阅读(386)  评论(0编辑  收藏  举报