C++ 【string模拟实现】

本文详细探讨了C++中如何模拟实现`std::string`类,包括构造函数、析构函数、拷贝构造函数、赋值运算符、resize、reserve、push_back、append、insert、erase、输入输出操作、迭代器、c_str、find和substr等功能的实现,并讨论了相关注意事项和优化技巧。

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

string模拟实现

构造函数+析构函数

拷贝构造函数:深拷贝

赋值运算符拷贝

resize和reserve

push_back && append

insert

erase

<< && >>

迭代器

迭代器模拟实现

c_str(cpp中使用了string,要和c语言兼容,用c去读文件等)

find和substr

getline练习题

运算符重载

to_string:从字符串转换-其他转字符串函数


string模拟实现

构造函数+析构函数

注意:1.空对象初始化时开一个空间:\0

2.写全缺省,隐含了一个\0,只要是常量字符串,后面都已\0为结尾

	/*string()  //无参构造函数
		:_str(new char[1])
		,_size(0)
		,_capacity(0)
	{
		_str[0] = '\0';
	}*/

	//string(const char* str = "")//strlen时间复杂度O(N)
	//	:_str(new char[strlen(str)+1])
	//	,_size(strlen(str))
	//	, _capacity(strlen(str))//capacity不包含\0,只统计有效字符
	//{
	//	strcpy(_str, str);
	//}

	string(const char* str = "")//全缺省,隐含了一个\0,只要是常量字符串,后面都已\0为结尾
	{
		_size = strlen(str);
		_capacity = _size;
		_str = new char[_capacity + 1];
		strcpy(_str, str);
	}

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


拷贝构造函数:深拷贝

默认的拷贝构造,代码崩溃原因:浅拷贝指向同一块空间并析构两次(默认生成拷贝构造对内置类型值拷贝) 

	void test_string2()
	{	
		string s1("hello world");
		string s2(s1);
		cout << s1.c_str() << endl;
		cout << s2.c_str() << endl;

	}

正确的普通写法

	string(const string& s)//s2(s1)
		:_str(new char[s._capacity+1])//capacity存储有效数据空间,每次都多开一个\0
		,_size(s._size)
		,_capacity(s._capacity)
	{
		strcpy(_str, s._str);
	}

正确的现代写法 --利用构造函数swap

把随机数换给tmp导致程序崩溃--析构释放随机空间 

	string(const string& s)//s2(s1)
	{
		string tmp(s._str);//tmp是打工人,s._str是const字符串,相当于调用构造函数,s2想要一样大的空间和一样大的值
		swap(_str, tmp._str);
		swap(_size, tmp._size);
		swap(_capacity, tmp._capacity);
	}

再改进:放nullptr,delete nullptr不会报错

	void swap(string& tmp)
	{
		::swap(_str, tmp._str);//::调用全局swap
		::swap(_size, tmp._size);
		::swap(_capacity, tmp._capacity);
	}

	string(const string& s)//s2(s1)
		:_str(nullptr)
		,_size(0)
		,_capacity(0)
	{
		string tmp(s._str);//tmp是打工人,s._str是const字符串,相当于调用构造函数
		swap(tmp);//s2和tmp交换
	}


赋值运算符拷贝

 默认的赋值代码崩溃原因:同样的浅拷贝报错,只是依次拷贝给s1,内存泄漏+析构两次

	void test_string3()
	{
		string s1("hello world");
		string s3("ww");
		s1 = s3;
	}

正确的普通写法(直接释放旧空间重新开辟)

  自己给自己赋值(释放后随机值拷贝给自己)解决方法:判断相等

    string& operator=(const string& s)
	{
		if (this != &s)
		{
			char* tmp  = new char[s._capacity + 1];
        //先开空间再释放,防止new失败抛异常破坏原数据
			strcpy(tmp, s._str);
			delete[] _str;
			_str = tmp;
			_size = s._size;
			_capacity = s._capacity;
		}
		return *this;
	}

现代写法

1.错误的写法,此处swap包含赋值,死循环

   string& operator=(const string& s)
	{
		if (this != &s)
		{
			string tmp(s);//调拷贝构造
			::swap(*this,tmp);
		}
		return *this;
	}

2.直接使用全局中的swap包含了一次拷贝构造,两次赋值,一共三次深拷贝,代价极高

正确的写法,swap成员变量换

	void swap(string& tmp)
	{
		::swap(_str, tmp._str);//::调用全局swap
		::swap(_size, tmp._size);
		::swap(_capacity, tmp._capacity);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

北方留意尘

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

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

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

打赏作者

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

抵扣说明:

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

余额充值