C++--string的模拟实现

一,引言

string的模拟实现是只对string对象中给的主要功能经行模拟实现,其目的是加强对string的底层了解,以便于在以后的学习或者工作中更加熟练的使用string。本文中的代码仅供参考并不唯一。

二,默认成员函数

string主要有三个成员变量,字符串指针--用于存放数据,size--记录有效数据,capacity--记录内存的大小。

1,构造函数

负责对成员变量进行初始化操作,当不传参数时,顺序表中只有\0用于表示顺序表的结束。当传入参数时,将传入的参数存入string对象中。具体实现如下:

cpp 复制代码
string( const char* str = "")
{
	_str = new char[strlen(str) + 1];
	_size = strlen(str);
	_capacity = strlen(str);
	strcpy(_str, str);
}

在进行开辟空间时多开了一个字节的空间,该字节的空间负责存放\0。

分别是无参调用,和带参调用。

2,拷贝构造函数

负责实现对象的深拷贝。为构造函数的一种。具体实现如下:

cpp 复制代码
string(string& str)
{
	_str = new char[str._capacity + 1];
	_size = str._size;
	_capacity = str._capacity;
	strcpy(_str, str._str);
}

初始化逻辑与实现原理基本相同。strcpy函数用于字符串复制,包含两个参数:第一个参数是目标地址,第二个参数是源地址。该函数会将源地址处直到'\0'结束符的所有字符(包括'\0')复制到目标地址所在位置。

将s1是由s2拷贝构造而来的。

3,析构函数

释放已开辟的内存空间并将指针置空,同时将相关参数清零,具体实现如下:

cpp 复制代码
~string()
{
	delete[]_str;
	_str = nullptr;
	_size = _capacity = 0;
}

s1被析构。

4,赋值重载

重载赋值运算符(=),将源对象内容完整复制到目标对象,实现对象间的深度赋值。

三,其他成员函数

1,c_str

返回string对象的字符数组成员的首地址。 具体实现如下:

cpp 复制代码
char* c_str()
{
	return this->_str;
}

2,size

返回string对象中有效数据的个数。具体实现如下:

cpp 复制代码
size_t size()const
{
	return this->_size;
}

3,capacity

返回string对象中的容量不包括\0。具体实现如下:

cpp 复制代码
size_t capacity() const
{
	return this->_capacity;
}

4,[]运算符重载

实现string对象某个字符的修改。具体实现如下:

cpp 复制代码
char& operator[](size_t pos)
{
	assert(pos < _size);
	return _str[pos];
}

返回的是该位置的引用可以对该对象的值进行修改。

对s1的第一个位置进行修改。

5,clear

清空对象内容,并将大小重置为0。具体实现如下:

cpp 复制代码
void clear()
{
	_str[0] = '\0';
	_size = 0;
}

6.reserve

当对象内存不足时,该函数负责执行扩容操作。具体实现如下:

cpp 复制代码
void string::reserve(size_t n)
{
	if (n > _capacity)
	{
		int com = _capacity == 0 ? n : _capacity * 2;
        if(com < n)
            {
                com = n;
            }
		char* ptr = new char[com + 1];
		strcpy(ptr, _str);
		delete[]_str;
		_str = ptr;
		ptr = nullptr;
		_capacity = com;

	}
}

当容量为零时,按需分配所需空间;若容量不为零,则比较当前需求与现有容量的两倍,取较大值以避免频繁扩容。注意,每次扩容时需额外预留一个字节用于存储字符串终止符'\0'。以下为测试用例演示:

cpp 复制代码
int main()
{
	Cao::string s2("fdasjl");
	cout << s2.capacity() << endl;
	s2.reserve(10);
	cout << s2.capacity() << endl;
	Cao::string s1;
	cout << s1.capacity() << endl;
	s1.reserve(10);
	cout << s1.capacity() << endl;
	return 0;
}

7,push_back

尾插单个字符。具体实现如下:

cpp 复制代码
void string::push_back(char ch)
{
	if (_size + 1 > _capacity)
	{
		reserve(_size + 1);
	}
	_str[_size] = ch;
	_size++;
	_str[_size] = '\0';
}

先判断容量了,再进行插入。

8,append

尾插字符串。具体实现如下:

cpp 复制代码
void string::append(const char* str)
{
	if (_size + strlen(str) > _capacity)
	{
		reserve(_size + strlen(str));
	}
	strcpy(_str + _size, str);
	_size = _size + strlen(str);

}

先进行容量判断,之后插入。

9,insert

在指定位置插入字符串,具体实现如下:

cpp 复制代码
void string::insert(size_t pos, const char* str)
{
	if (_size + strlen(str) > _capacity)
	{
		reserve(_size + strlen(str));
	}
	strcpy(_str + pos + strlen(str), _str + pos);
	*this += str;
	_size += strlen(str);
}

先评估容量,再迁移数据腾出目标位置,最后插入字符串。

10,erase

指定位置,指定区域进行删除数据。具体实例如下:

cpp 复制代码
void string::erase(size_t pos, size_t len )
{
	assert(pos < _size);
	if (pos + len >= _size)
	{
		_str[pos] = '\0';
		_size = _size - pos;
	}
	else
	{
		strcpy(_str + pos, _str + pos + len);
		_size = _size - len;
	}
}

分为两种情况,第一种指定长度之后还存在数据。第二种情况是,指定长度之后没有数据。

11,find

查找字符串,找到之后返回首个字符的下标。没有找到返回npos。具体实现如下:

cpp 复制代码
size_t string::find(const char* str, size_t pos )
{
	assert(pos < _size);
	{
		char* ptr = _str + pos;
		return  strstr(ptr, str) - _str ;
	}
}

四,总结

关于函数的具体功能,可以参考string这篇文章。在练习过程中,不必追求完美实现,重点在于理解string的底层代码逻辑及其使用方法。

相关推荐
加油搞钱加油搞钱3 分钟前
鹰盾加密器“一机一码”技术全维度剖析:从底层实现到生态防护体系
开发语言·网络·python
朝朝又沐沐6 分钟前
基于算法竞赛的c++编程(28)结构体的进阶应用
开发语言·c++·算法
蔡蓝20 分钟前
设计模式-备忘录模式
java·设计模式·备忘录模式
豪斯有话说20 分钟前
C++_红黑树
开发语言·数据结构·c++
莱茵不哈哈21 分钟前
C/C++八股文
开发语言·c++
迢迢星万里灬24 分钟前
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
java·spring boot·spring·mybatis·spring mvc·面试指南
只有干货26 分钟前
java若依 excel 导出高度自适应
java·excel
风痕~~31 分钟前
java实现word末尾添加图片的两种方式
java·word
qqxhb44 分钟前
零基础设计模式——行为型模式 - 迭代器模式
java·设计模式·go·迭代器模式
白玉cfc1 小时前
Objective-C常用命名规范总结
开发语言·ios·objective-c