前言
在这篇博客里将详细说说C++中的STL,通过这篇我们可以学习到什么是STL,以及STL的六大组件,STL具有的缺陷,最后看看string类及面试会让模拟实现string类的操作。
1.STL
STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包含了数据结构与算法的软件框架。
STL的版本:原始版本、P.J.版本、RW版本、SGI版本
STL的六大组件:
算法:find、swap、reverse、sort、merge.…
迭代器:iterator、const_iterator、reverse_iterator、const_reverse_iterator.
容器:string、vector、list、deque、map、set、multimap、multiset
仿函数:greater、less.…
配接器:stack、queue、priority_queue
空间配置器:allocator
STL的缺陷:
1.STL库的更新太慢。
2. STL没有支持线程安全。并发环境下需要我们自己加锁。且锁的粒度是比较大的。
3. STL极度的追求效率,导致内部比较复杂。比如类型萃取,迭代器萃取。
4. STL的使用会有代码膨胀的问题,比如使用vector/vector/vector这样会生成多份代码。
2.string类
2.1 string类:
(1)string是表示字符串的字符串类
(2) 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
(3)string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> string;
(4)不能操作多字节或者变长字符的序列。
(5)在使用string类时,必须包含#include头文件以及using namespace std;
2.2string类对象的常见构造
(1)string s1;构造空的string类对象s1
(2)string s2(“hello word”);用c格式字符串构造string对象s2
(3)string s3(s2);拷贝构造s3对象
void test()
{
string str;//创建空的str对象
string str2("hello world");// 用C格式字符串构造string类对象str2
string str3(str2);//拷贝构造对象str3
}
2.3string类对象的容量操作
(1)size/length;返回字符串有效字符长度,不包含’\0’。
(2)capacity;返回空间总大小。增容一般是按照原来的1.5倍增加,capacity初始值为15。
(3)empty;检测字符串是否为空,是则返回true,否则返回false。
string str("abcdef");
cout << str.size() << endl;//size为6
cout << str.length() << endl;//length为6
cout << str.capacity() << endl;//capacity为15
if (str.empty())
cout << "字符串为空" << endl;
else
cout << "字符串不为空" << endl;
(4)resize;修改有效字符的个数。如果有效字符的个数增加,则新增加的位置填充’\0’。如果大小减小,则不会填充。
(5)reserve;修改容量,提前开好空间,避免频繁的增容,提高代码的效率,而且只能增加容量。
string str("abcdef");
str.resize(10);//修改size为10,在剩余的部分用'\0'填充
str.resize(10,'5');//abcdef5555
str.reserve(60);//修改容量
2.4string类对象的访问及遍历操作
(1)for+oprerator[];
void test()
{
string str("abcde");
//第一种方式:for+operator[]
for (size_t i = 0; i < str.size(); ++i)
{
cout << str[i] << endl;
}
}
(2)begin+end/rbegin+rend;begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭代器。
//第二种方式:迭代器
string str("abcde");
string::iterator it = str.begin();
while (it != str.end())
{
cout << *it << endl;
++it;
}
(3)范围for;c++11支持更简洁的范围for方式。
//第三种方式:范围for
string str("abcde");
for (auto& e : str)
{
cout << e << endl;
}
2.5string类对象的修改操作
(1)push back;在字符串末尾插入字符
(2)append;在字符串后追加一个字符串
(3)operator+=;在字符串后追加字符串str
(4)c_str;返回c格式字符串
string str;
str.push_back(' '); // 在str后插入空格
str.append("hello"); // 在str后追加一个字符"hello"
str += 'w'; // 在str后追加一个字符'w'
str += "orld"; // 在str后追加一个字符串"orld"
cout << str << endl;
cout << str.c_str() << endl; // 以C语言的方式打印字符串
(5)find+npos;从字符串pos位置开始往后找字符c,返回该字符在字符中的位置。
(6)rfind;从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
(7)substr;在str中从pos位置开始,截取n个字符,然后将其返回
2.6 string类非成员函数
(1)operator+;和+=操作一样,但是此处是传值返回,效率低,一般更推荐使用+=操作。
(2)operator>>;输入运算符重载
(3)operator<<;输出运算符重载
(4)getline;获取一行字符串
(5)relational operators;大小 比较
3.string类的模拟实现
模拟实现string类最主要是实现string类的构造、拷贝构造、赋值运算符重载以及析构函数的主要操作。
class String
{
public:
//默认构造函数
String(const char* str = "")
:_data(new char[strlen(str) + 1])
{
strcpy(_data,str);
}
//拷贝构造函数现代写法,借助构造函数在创建局部对象时,
//进行空间申请+内容拷贝,通过交换成员的执行,最终达到拷贝构造的目的
String(const String& str)
:_data(nullptr)
{
String tmp(str._data);
swap(_data,tmp._data);
}
//赋值运算符重载现代写法:复用拷贝
//借助拷贝构造完成空间申请+内容拷贝
//借助局部对象的析构函数完成当前对象原有资源的释放
String& operator=(String str)
{
swap(_data, str._data);
return *this;
}
//析构函数
~String()
{
if (_data)
{
delete[] _data;
_data = nullptr;
}
}
private:
char* _data;
};