核心要点速览

  • C 风格字符串:以'\0'结尾的字符数组,依赖cstring库函数,无安全检查(易溢出)
  • C++ std::string:动态管理、安全便捷,支持 SSO(小字符串优化),提供丰富成员方法
  • 拷贝关键:C 语言strcpy不安全、strncpy需补'\0'strlcpy安全非标准;C++ 直接用拷贝构造 / 赋值 /assign

一、C 风格字符串(char[]

本质是'\0'(空字符)为结束标记的字符数组,'\0'是字符串终止的核心标识。

1. 初始化(易错)

1
2
3
4
5
6
7
// 正确写法
char str1[] = "hello"; // 自动添加'\0',数组长度6(h e l l o \0)
char str2[] = {'h','i','\0'}; // 手动添加'\0',长度3
char str3[10] = "hi"; // 未初始化部分自动填'\0',长度10

// 错误写法
char str4[] = {'h','e','l','l','o'}; // 无'\0',strlen会越界扫描(未定义行为)

2. 主要操作函数(cstring库)

函数 功能 陷阱与注意事项
strlen(s) 计算'\0'前的字符数(不含'\0' '\0'时越界扫描;返回值是size_t(无符号),避免与 int 比较
strcpy(dst, src) 拷贝srcdst(含'\0' dst容量不足会溢出;无长度检查,不安全
strcat(dst, src) 拼接srcdst末尾 dst已含'\0';总长度超dst容量会溢出
strcmp(s1, s2) 字典序比较 返回 0 表示相等,正数s1>s2、负数s1<s2;不可用==比较字符串

二、C++ std::string

动态管理的字符串类,无需手动处理'\0',安全便捷,是 C++ 开发首选。

1. 核心特性

  • 动态大小:自动扩容,支持push_backappend等操作
  • 安全保障:at()方法越界抛异常,[]无检查(需自行确保合法)
  • 便捷操作:重载+(拼接)、==(比较)等运算符
  • 内存优化:小字符串优化(SSO),短字符串存栈上(无需堆分配)

2. 常用方法

方法 功能 注意事项
size()/length() 返回字符数(不含'\0' 功能完全一致,仅历史原因并存
c_str()/data() 转为 C 风格字符串(const char* 指针有效期与string绑定,修改string后可能失效
substr(pos, len) 提取子串(从pos开始,长度len pos越界抛异常;len超范围则取到字符串末尾
find(sub, pos) pos查找sub,返回起始索引 未找到返回string::npos(需用该常量判断,而非 - 1)
reserve(n) 预分配n个字符内存 提升扩容效率,不改变size(实际字符数)
resize(n, c) 调整字符数为n,不足补字符c 可能截断长字符串或填充短字符串

3. 深入特性

(1)小字符串优化(SSO)

  • 短字符串(通常长度≤15):直接存储在std::string对象内部(栈内存),无堆分配开销。
  • 长字符串:存储在堆内存,string对象仅保存指针、长度、容量信息。

(2)迭代器失效

  • 触发场景:push_backappendresize等可能导致扩容的操作,底层内存重分配。
  • 后果:原有迭代器、指针、引用失效(访问即未定义行为)。

(3)C 风格字符串转换

  • std::string → C 风格:c_str()(返回const char*,不可修改)。
  • C 风格 → std::string:直接赋值(string s = c_style_str;),自动识别'\0'

三、字符串拷贝

1. C 语言拷贝函数(cstring库)

(1)strcpy(基础,不安全)

  • 核心逻辑:拷贝srcdst,直到'\0'(含'\0'),无长度检查。
  • 特点:支持链式操作;dst容量不足会缓冲区溢出(高危)。

(2)strncpy(带长度限制,需补'\0'

  • 核心逻辑:最多拷贝n个字节;src长度≤n时补'\0',>n 时不补'\0'
  • 特点:降低溢出风险,但需手动确保dst'\0'结尾(否则不是合法字符串)。

(3)strlcpy(安全首选,非标准)

  • 核心逻辑:目标缓冲区大小dest_size,最多拷贝dest_size-1字节,强制补'\0'
  • 特点:完全避免溢出;返回src长度(不含'\0');非 ISO C 标准,广泛支持(Linux/BSD)。

(4)memcpy(按字节拷贝,通用)

  • 核心逻辑:拷贝n个字节,不依赖'\0',适用于任意数据(字符串、数组、结构体)。
  • 字符串场景注意:需手动计算src长度(含'\0'),避免遗漏终止符。

2. C++ std::string拷贝方式

  • 拷贝构造:string dest(src);
  • 赋值运算符:string dest = src;
  • assign方法:dest.assign(src, pos, len);(从srcpos位拷贝len个字符)