文章目录
- [【C++ STL】string类](#【C++ STL】string类)
-
- [1. C++11 语法补充(前置知识)](#1. C++11 语法补充(前置知识))
-
- [1.1 auto 关键字](#1.1 auto 关键字)
- [1.2 范围 for 循环](#1.2 范围 for 循环)
- [2. 标准库中的 string 类](#2. 标准库中的 string 类)
-
- [2.1 常见构造函数](#2.1 常见构造函数)
- [2.2 容量操作](#2.2 容量操作)
- [2.3 修改与访问](#2.3 修改与访问)
- [3. string 底层结构的差异 (VS vs G++)](#3. string 底层结构的差异 (VS vs G++))
-
- [3.1 VS (Visual Studio) 结构](#3.1 VS (Visual Studio) 结构)
- [3.2 G++ (Linux) 结构](#3.2 G++ (Linux) 结构)
- [4. 对于模拟实现string 类的浅拷贝问题](#4. 对于模拟实现string 类的浅拷贝问题)
-
- [4.1 浅拷贝及其危害](#4.1 浅拷贝及其危害)
- [4.2 现代版深拷贝](#4.2 现代版深拷贝)
- 总结
【C++ STL】string类
摘要: 在C语言中,字符串以
\0结尾,相关库函数与数据分离,且需用户管理内存,易越界。C++ STL 提供的string类将数据与操作结合,极大提高了开发效率。
1. C++11 语法补充(前置知识)
在学习 string 及后续容器前,需掌握两个高效的 C++11 特性。
1.1 auto 关键字
auto 不再是简单的存储类型指示符,而是类型指示符,让编译器在编译期自动推导变量类型。
使用规则:
- 指针与引用: 声明指针时
auto和auto*等效;声明引用时必须加&。 - 多变量声明: 同一行声明多个变量时,类型必须相同,因为编译器只根据第一个变量推导类型。
- 限制:
auto不能作为函数参数(但可做返回值),且不能直接声明数组。
cpp
int main() {
int x = 10;
auto a = &x; // 推导为 int*
auto* b = &x; // 推导为 int*
auto& c = x; // 推导为 int&
// auto arr[] = {1, 2, 3}; // 错误:不能声明数组
return 0;
}
1.2 范围 for 循环
范围 for 能够自动迭代、取数据并判断结束,极大简化了容器遍历。
原理: 范围 for 的底层通过替换为迭代器实现。
cpp
string str("hello world");
// 1. 遍历打印
for (auto ch : str) {
cout << ch << " ";
}
// 2. 遍历并修改(必须用引用)
for (auto& ch : str) {
ch += 1;
}
2. 标准库中的 string 类
使用时请包含头文件 #include <string>。
2.1 常见构造函数
| 函数名称 | 功能说明 |
|---|---|
string() |
构造空字符串 |
string(const char* s) |
用 C 格式字符串构造 |
string(size_t n, char c) |
生成 n 个字符 c 的字符串 |
string(const string& s) |
拷贝构造函数 |
2.2 容量操作
| 函数名称 | 功能说明 |
|---|---|
size() |
返回字符串有效字符长度(最常用) |
capacity() |
返回空间总大小 |
empty() |
检测字符串是否为空 |
clear() |
清空字符内容,但不缩减容量 |
reserve(n) |
预留空间,不改变有效元素个数 |
resize(n, c) |
改变长度,多出的空间用字符 c 填充 |
重点区分:
reserve只影响容量大小;resize既可能改变容量,也会实实在在改变size(填充或截断数据)。
2.3 修改与访问
- operator[]: 像数组一样通过索引
s[i]访问字符。 - operator+=: 推荐使用,可直接追加字符或字符串。
- c_str(): 返回 C 格式字符串,常用于调用 C 语言接口。
- find(): 从指定位置向后查找,找不到则返回
string::npos。
3. string 底层结构的差异 (VS vs G++)
3.1 VS (Visual Studio) 结构
VS 采用 SBO (Small Buffer Optimization) 优化:
- 32位下占 28字节。
- 包含一个联合体:长度 < 16 字节时存放在内部数组,提高效率;>= 16 字节时才在堆上开辟空间。
3.2 G++ (Linux) 结构
G++ 采用 COW (Copy-On-Write,写时拷贝) 技术:
- 32位下仅占 4字节(一个指针)。
- 指针指向的堆空间包含:有效长度、容量、引用计数及实际数据。
4. 对于模拟实现string 类的浅拷贝问题
4.1 浅拷贝及其危害
如果不写拷贝构造,系统默认的拷贝会导致两个对象指向同一块空间。这会引发:
- 修改互相影响。
- 析构崩溃 (同一块空间被
delete两次)。
4.2 现代版深拷贝
利用构造函数和 swap 函数,让临时对象帮我们完成繁琐的工作。
cpp
class String {
public:
// 构造
String(const char* str = "") {
_str = new char[strlen(str) + 1];
strcpy(_str, str);
}
// 拷贝构造:现代写法
String(const String& s) : _str(nullptr) {
String tmp(s._str); // 调用构造函数开空间
swap(_str, tmp._str); // 交换资源
}
// 赋值重载:传值参数触发拷贝构造产生副本 s
String& operator=(String s) {
swap(_str, s._str); // 副本 s 销毁时顺便带走旧资源
return *this;
}
~String() {
delete[] _str;
}
private:
char* _str;
};
总结
掌握 string 类不仅要会用其丰富的接口,更要理解底层深浅拷贝的逻辑及不同编译器的实现差异。在算法面试中,大数加法和双指针反转是极其常见的考点,建议熟练背诵相关模板。