一、学习 string 类的缘由

(一)C 语言字符串的局限

  1. 存储形式:以 '\0' 结尾的字符集合

  2. 操作问题:依赖 str 系列库函数,与字符串分离,不符合 OOP 思想

  3. 管理风险:底层空间需用户自行管理,易出现越界访问

(二)实际应用需求

  1. OJ 题目:多以 string 类形式出题

  2. 工作场景:为追求简单、方便、快捷,优先使用 string 类,极少用 C 库字符串操作函数

(三)相关面试题预览

  1. 字符串转整形数字

  2. 字符串相加

二、标准库中的 string 类

(一)string 类基础认知

  1. 本质定义:表示字符序列的类,是 basic_string 模板类的实例(typedef basic_string<char, char_traits, allocator> string

  2. 接口特点:接口类似标准字符容器,额外添加单字节字符字符串操作特性

  3. 局限:无法处理多字节或变长字符序列(如 UTF-8),相关成员操作按字节进行

  4. 使用前提:包含<string>头文件,且使用using namespace std;

(二)常用接口详解

1. 类对象构造接口

函数名称

功能说明

string()(重点)

构造空的 string 类对象(空字符串)

string(const char* s)(重点)

用 C 格式字符串构造 string 类对象

string(size_t n, char c)

构造包含 n 个字符 c 的 string 类对象

string(const string& s)(重点)

拷贝构造函数,用已有 string 对象构造新对象

2. 容量操作接口

函数名称

功能说明

注意事项

size()(重点)

返回有效字符长度

length()底层实现一致,为适配其他容器接口设计,更常用

length()

返回有效字符长度

功能同size()

capacity()

返回空间总大小

与实际可存储字符的空间相关

empty()(重点)

检测字符串是否为空,空返回 true,否则 false

仅判断有效字符是否为空

clear()(重点)

清空有效字符

不改变底层空间大小

reserve()(重点)

为字符串预留空间

参数小于当前底层空间大小时,不改变容量

resize()(重点)

将有效字符个数改为 n,多余空间用指定字符填充

增多字符时可能改变底层容量,减少字符时底层空间不变;无指定填充字符时用 0 填充

3. 访问及遍历操作接口

函数名称

功能说明

operator[](重点)

返回 pos 位置的字符,const string 对象可调用

begin() + end()

begin()获取首字符迭代器,end()获取最后一个字符下一个位置的迭代器

rbegin() + rend()

rbegin()获取反向迭代器(指向最后一个字符),rend()获取反向迭代器(指向首字符前一个位置)

范围 for

C++11 新增,简洁遍历字符串

4. 修改操作接口

函数名称

功能说明

注意事项

push_back

在字符串尾部插入字符 c

仅能插单个字符

append

在字符串尾部追加字符串

可追加字符串

operator+=(重点)

在字符串尾部追加字符或字符串

功能灵活,使用频率高

c_str()(重点)

返回 C 格式字符串(以 '\0' 结尾)

便于兼容 C 语言操作

find + npos(重点)

从 pos 位置往后找字符 c,返回其位置

npos为无符号整型常量,表未找到

rfind

从 pos 位置往前找字符 c,返回其位置

find查找方向相反

substr

从 pos 位置开始截取 n 个字符,返回新字符串

用于获取子串

5. 非成员函数接口

函数

功能说明

注意事项

operator+

字符串拼接

传值返回,深拷贝效率低,尽量少用

operator>>(重点)

输入运算符重载

用于读取字符串

operator<<(重点)

输出运算符重载

用于输出字符串

getline(重点)

获取一行字符串

可读取含空格的字符串,区别于cin>>

relational operators(重点)

字符串大小比较

按字符 ASCII 码值比较

(三)不同编译器下的 string 结构

1. VS(32 位平台)

  • 总占用空间:28 字节

  • 内部结构:含联合体(存储字符串,长度 < 16 用固定数组,≥16 用堆空间)、size_t(存字符串长度)、size_t(存堆空间总容量)、指针(其他功能)

  • 设计优势:短字符串(<16 字符)无需堆空间,效率高

2. g++(32 位平台)

  • 总占用空间:4 字节(仅含一个指针)

  • 实现方式:写时拷贝,指针指向堆空间,堆空间含空间总大小、有效长度、引用计数、字符串存储区

三、string 类模拟实现

(一)经典问题分析

  1. 默认拷贝构造与赋值重载的缺陷:浅拷贝导致多个对象共享同一块内存,销毁时重复释放引发崩溃

  2. 浅拷贝定义:也称位拷贝,仅拷贝对象值,共享资源,易引发访问违规

(二)深拷贝实现

1. 传统版写法

cpp

运行

class String {
public:
// 构造函数
String(const char* str = "");
// 拷贝构造函数
String(const String& s);
// 赋值运算符重载
String& operator=(const String& s);
// 析构函数
~String();
private:
char* _str;
};
  • 构造:为字符串分配空间(含 '\0'),拷贝字符

  • 拷贝构造:为新对象独立分配空间,拷贝源对象字符串

  • 赋值重载:先判断是否自赋值,再分配新空间、拷贝字符、释放原空间

  • 析构:释放空间,置空指针

2. 现代版写法

cpp

运行

class String {
public:
// 构造函数
String(const char* str = "");
// 拷贝构造函数(利用临时对象交换资源)
String(const String& s);
// 赋值运算符重载(参数传值,利用临时对象交换资源)
String& operator=(String s);
// 析构函数
~String();
private:
char* _str;
};
  • 拷贝构造:先将_str置空,创建临时对象,交换_str与临时对象的_str

  • 赋值重载:参数传值生成临时对象,交换_str与临时对象的_str,临时对象销毁时释放原资源

(三)写时拷贝(了解)

  1. 实现原理:基于浅拷贝,增加引用计数记录资源使用者个数

  2. 引用计数操作:构造时计数为 1,新增对象时计数 + 1,对象销毁时计数 - 1;计数为 0 时释放资源

  3. 特点:读取时共享资源,修改时才拷贝资源,存在读取缺陷

posted on 2025-10-10 16:24  lxjshuju  阅读(10)  评论(0)    收藏  举报