C++STL标准模板库——string类的深浅拷贝

一、深拷贝VS浅拷贝

面试官总喜欢让面试者实现一个string类,最主要实现的string类的构造、拷贝构造、赋值运算符重载以及析构函数。但是如果我们只实现一部分功能,其它采用编译器默认实现的功能,就涉及到了深浅拷贝问题,如下我们实现一段string代码

//string浅拷贝
namespace leon
{
	class string
	{
	public:
		//string构造函数
		string(const char* str = "")
		{
			assert(str);	//如果str为nullptr直接报错
			_str = new char[strlen(str) + 1];
			strcpy(_str, str);
		}

		~string()
		{
			if (_str)
			{
				delete[] _str;
				_str = nullptr;
			}
		}

	private:
		char *_str;

	};
}

void Teststring1()
{
	leon::string s1("hello");
	leon::string s2(s1);
}

1.1 浅拷贝

C++STL标准模板库——string类的深浅拷贝_第1张图片

上述string类没有显式定义其拷贝构造函数与赋值运算符重载,此时编译器会合成默认的,当用s1构造s2时,编译器会调用默认的拷贝构造。最终导致的问题是,s1、s2共用同一块内存空间,在释放时同一块
空间被释放多次而引起程序崩溃,这种拷贝方式,称为浅拷贝

Q1:什么是浅拷贝?

当一个对象构造另一个对象(一个对象给另一个对象赋值时),后者的指针类型成员指向前者指针类型成员指向的空间,当析构这两个对象时,会对同一块空间重复释放。

Q2:什么是深拷贝?

当一个对象构造另一个对象(一个对象给另一个对象赋值的时候),被赋值对象的指针类型成员指向新开辟的一块空间,新空间指向的内容和赋值对象指向的内容相同。

解决浅拷贝一种方式就是引入深拷贝。

1.2 深拷贝

如果一个类中涉及到资源的管理,其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出。一般情况都是按照深拷贝方式提供。

我们显式定义拷贝构造函数

string(const string& s)
{
    _str = new char[strlen(s._str) + 1];
    strcpy(_str, s._str);
}

C++STL标准模板库——string类的深浅拷贝_第2张图片

<1> 模拟实现string(传统写法)

	class string {
	public:
		string(const char* str = "")
		{
			if (nullptr == str)
			{
				assert(false);
				return;
			}
			//开辟和str一样的空间,并拷贝赋值,strcpy会拷贝'\0'
			_str = new char[strlen(str) + 1];
			strcpy(_str, str);
		}

		string(const string& s)
			:_str(new char[strlen(s._str) + 1])
		{
			strcpy(_str, s._str);
		}

		string& operator=(const string& s)
		{
			if (this != &s)
			{
				char* pStr = new char[strlen(s._str) + 1];
				strcpy(pStr, s._str);
				delete[] _str;
				_str = pStr;
			}

			return *this;
		}

		~string()
		{
			if (_str)
			{
				delete[] _str;
				_str = nullptr;
			}
		}

	private:
		char* _str;
	};

<2> 模拟实现string(现代写法)


	class string {
	public:
		string(const char* str = "")
		{
			if (nullptr == str)
			{
				assert(false);
				return;
			}
			//开辟和str一样的空间,并拷贝赋值,strcpy会拷贝'\0'
			_str = new char[strlen(str) + 1];
			strcpy(_str, str);
		}

		string(const string& s)
		{
			string strtmp(s._str);
			std::swap(_str, strtmp._str);
		}

		string& operator=(string s)
		{
			std::swap(_str, s._str);
			return *this;
		}

		~string()
		{
			if (_str)
			{
				delete[] _str;
				_str = nullptr;
			}
		}

	private:
		char* _str;
	};

你可能感兴趣的:(C++,深拷贝,浅拷贝,string,STL)