C++--string的模拟实现
一,引言
string的模拟实现是只对string对象中给的主要功能经行模拟实现,其目的是加强对string的底层了解,以便于在以后的学习或者工作中更加熟练的使用string。本文中的代码仅供参考并不唯一。
二,默认成员函数
string主要有三个成员变量,字符串指针--用于存放数据,size--记录有效数据,capacity--记录内存的大小。
1,构造函数
负责对成员变量进行初始化操作,当不传参数时,顺序表中只有\0用于表示顺序表的结束。当传入参数时,将传入的参数存入string对象中。具体实现如下:
string( const char* str = "")
{_str = new char[strlen(str) + 1];_size = strlen(str);_capacity = strlen(str);strcpy(_str, str);
}
在进行开辟空间时多开了一个字节的空间,该字节的空间负责存放\0。
分别是无参调用,和带参调用。
2,拷贝构造函数
负责实现对象的深拷贝。为构造函数的一种。具体实现如下:
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,析构函数
释放已开辟的内存空间并将指针置空,同时将相关参数清零,具体实现如下:
~string()
{delete[]_str;_str = nullptr;_size = _capacity = 0;
}
s1被析构。
4,赋值重载
重载赋值运算符(=),将源对象内容完整复制到目标对象,实现对象间的深度赋值。
三,其他成员函数
1,c_str
返回string对象的字符数组成员的首地址。 具体实现如下:
char* c_str()
{return this->_str;
}
2,size
返回string对象中有效数据的个数。具体实现如下:
size_t size()const
{return this->_size;
}
3,capacity
返回string对象中的容量不包括\0。具体实现如下:
size_t capacity() const
{return this->_capacity;
}
4,[]运算符重载
实现string对象某个字符的修改。具体实现如下:
char& operator[](size_t pos)
{assert(pos < _size);return _str[pos];
}
返回的是该位置的引用可以对该对象的值进行修改。
对s1的第一个位置进行修改。
5,clear
清空对象内容,并将大小重置为0。具体实现如下:
void clear()
{_str[0] = '\0';_size = 0;
}
6.reserve
当对象内存不足时,该函数负责执行扩容操作。具体实现如下:
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'。以下为测试用例演示:
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
尾插单个字符。具体实现如下:
void string::push_back(char ch)
{if (_size + 1 > _capacity){reserve(_size + 1);}_str[_size] = ch;_size++;_str[_size] = '\0';
}
先判断容量了,再进行插入。
8,append
尾插字符串。具体实现如下:
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
在指定位置插入字符串,具体实现如下:
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
指定位置,指定区域进行删除数据。具体实例如下:
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。具体实现如下:
size_t string::find(const char* str, size_t pos )
{assert(pos < _size);{char* ptr = _str + pos;return strstr(ptr, str) - _str ;}
}
四,总结
关于函数的具体功能,可以参考string这篇文章。在练习过程中,不必追求完美实现,重点在于理解string的底层代码逻辑及其使用方法。