模拟实现string类—现代写法

模拟实现string类—现代写法

c++面试常见题——模拟实现一个string类

时间有限,我们不能将string类完整模拟实现出来,但是至少模拟实现的string类要具备正确的资源管理能力
比如说构造、析构、拷贝、赋值运算符重载

模拟实现string类的现代版写法

之前我们学习的模拟实现string类是传统写法。

现代版讲究一个别人帮我开空间,自己能简洁就简洁。

先给个基础的构造函数

namespace wzf
{
	class string
	{
	public:
		string(const char* str = "")
		{
			_str = new char[strlen(str) + 1];
			strcpy(_str, str);
		}
        
		~string()
		{
			delete[] _str;
			_str = nullptr;
		}
	private:
		char* _str;
	};

现代版写法的拷贝构造:

	 拷贝构造的传统写法
	//string(const string& s)
	//{
	//	_str = new char[strlen(s._str) + 1];
	//	strcpy(_str, s._str);
	//}

	// 拷贝构造的现代写法
	string(const string& s)
		:_str(nullptr) // 这里一定要有不然就会报错
	{
		string tmp(s._str); // 调用string(const char* str = "")构造函数
		swap(_str, tmp._str); // 让tmp的内容和_str交换。这样_str就是我们想要的
	}

为什么:_str(nullptr) 这个一定要存在,因为我们在swap(_str, tmp._str);的时候,会将**_str的值传给tmp._str**,但是_str是没有初始化的内容,在出了作用域的时候,调用tmp的析构函数,释放未初始化的内容,就会导致代码崩溃。

现代版写法的赋值运算符重载:

赋值运算符重载的现代写法的思想——深拷贝我需要做,但是我自己不去做,我让其他函数去做。

		 赋值运算符重载的现代写法
		//string& operator=(const string& s)
		//{
		//	if (this != &s)
		//	{
		//		string tmp(s); // 开辟空间的事情不是自己干了,让别人帮自己干
		//		swap(_str, tmp._str); // tmp干完事情之后再交换给_str
		//	} //tmp出了作用域还会调用析构函数,将this的源数据清理

		//	return *this;
		//}

		// 更简单的写法 
		string& operator=(string s)// s会调用拷贝构造,s就是我们想要的,交换就行。
		{
			swap(_str, s._str);
			return *this;
		}// s在函数作用域结束时自己就会析构

string s这里的s会调用拷贝构造,假设s1 = s3,s就会拷贝构造s3,s就是我们想要的东西,那我们就去交换它swap(_str, s._str);,并且我们把s1的内容交换给s,s出了函数栈帧就会调用析构函数,就会将我们不要的资源清理掉,一举两得。

测试

实现测试之前要实现两个接口

		size_t size()
		{
			return strlen(_str);
		}

		char& operator[](size_t i)
		{
			return _str[i];
		}

测试代码:

	void test1()
	{
		string s1("hello");
		string s2(s1);
		string s3;
		s3 = s2;

		for (int i = 0; i < s2.size(); i++)
		{
			cout << s2[i];
		}
		cout << endl;

		for (int i = 0; i < s3.size(); i++)
		{
			cout << s3[i];
		}
		cout << endl;
	}

更完整的模拟实现—现代写法

namespace wzf
{
	class string
	{
	public:
		string(const char* str = "")
		{
			_size = _capacity = strlen(str);
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}

		~string()
		{
			delete[] _str;
			_str = nullptr;
			_size = _capacity = 0;
		}

		// 拷贝构造的现代写法
		string(const string& s)
			:_str(nullptr) // 这里一定要有不然就会报错
			,_size(0)
			,_capacity(0)
		{
			string tmp(s._str); // 调用string(const char* str = "")构造函数
			swap(tmp); // 让tmp的内容和*this交换。这样*this就是我们想要的
			// this->swap(tmp);
		}

		void swap(string& s)
		{
			::swap(_str, s._str); // ::的意思是不要调用自己,调用全局域的swap
			::swap(_size, s._size);
			::swap(_capacity, s._capacity);
		}

		// 更简单的写法 
		string& operator=(string s)// s会调用拷贝构造,s就是我们想要的,交换就行。
		{
			swap(s); // this->swap(s);
			return *this;
		}// s在函数作用域结束时自己就会析构

		size_t size()
		{
			return _size;
		}

		size_t capacity()
		{
			return _capacity;
		}

		char& operator[](size_t i)
		{
			return _str[i];
		}

	private:
		char* _str;
		size_t _size;
		size_t _capacity;
	};


	void test1()
	{
		string s1("hello");
		string s2(s1);
		string s3;
		s3 = s2;

		for (int i = 0; i < s2.size(); i++)
		{
			cout << s2[i];
		}
		cout << endl;
		cout << s2.capacity() << endl;
		cout << s2.size() << endl;

		for (int i = 0; i < s3.size(); i++)
		{
			cout << s3[i];
		}
		cout << endl;
		cout << s3.capacity() << endl;
		cout << s3.size() << endl;

	}
}

**总结:**现代写法是非常方便和简洁的一种写法。在以后学习其他的容器中我们也会使用这个写法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值