C++中std::string和std::string_view使用详解和示例

std::string

一、std::string 简介

std::string 是 C++ 标准库提供的字符串类,封装了动态管理的字符数组,功能比传统的 C 风格字符串(char*)更强大、安全、易用。

属于头文件:<string>

所在命名空间:std

主要优点:

  • 自动内存管理(不需要手动分配/释放)
  • 提供丰富的字符串操作函数(拼接、查找、替换等)
  • 与流(如 cin / cout)兼容性好
  • 支持下标访问与迭代器

二、基本用法示例

cpp 复制代码
#include <iostream>
#include <string>

int main() {
    std::string s1 = "Hello";
    std::string s2 = "World";
    std::string s3 = s1 + " " + s2; // 拼接

    std::cout << s3 << std::endl; // 输出:Hello World

    std::cout << "字符串长度:" << s3.length() << std::endl;
    std::cout << "第二个字符:" << s3[1] << std::endl;

    return 0;
}

三、常用成员函数汇总(+ 示例)

方法 说明 示例
.size() / .length() 获取字符串长度 s.length()
.empty() 判断是否为空 if (s.empty())
.at(i) 安全访问第 i 个字符(带边界检查) s.at(0)
.append(str) 追加字符串 s.append(" World")
.insert(pos, str) 插入子串 s.insert(5, ",")
.erase(pos, len) 删除部分内容 s.erase(5, 1)
.replace(pos, len, str) 替换部分内容 s.replace(0, 5, "Hi")
.substr(pos, len) 截取子串 s.substr(0, 5)
.find(str) 查找子串位置 s.find("llo")
.rfind(str) 从后向前查找 s.rfind("o")
.compare(str) 字符串比较(返回值类似 strcmp) s.compare("abc")
.c_str() 转为 C 风格字符串(返回 const char* printf("%s", s.c_str())

四、遍历方式

cpp 复制代码
std::string s = "Hello";

// 方式1:下标访问
for (size_t i = 0; i < s.size(); ++i)
    std::cout << s[i] << ' ';

// 方式2:范围 for 循环
for (char c : s)
    std::cout << c << ' ';

// 方式3:迭代器
for (auto it = s.begin(); it != s.end(); ++it)
    std::cout << *it << ' ';

五、与 C 字符串的互转

cpp 复制代码
std::string cppStr = "hello";
const char* cStr = cppStr.c_str();  // C++ -> C

std::string newStr(cStr);           // C -> C++

六、注意事项

  • string::at() 带边界检查,安全但略慢;[] 不检查越界。
  • std::getline(cin, s) 配合时注意清除输入缓冲区。
  • 不要对 .c_str() 返回的指针进行修改,它是只读的。

七、实战小示例:字符串反转

cpp 复制代码
#include <iostream>
#include <string>
#include <algorithm>

int main() {
    std::string s = "abcdefg";
    std::reverse(s.begin(), s.end());
    std::cout << s << std::endl;  // 输出:gfedcba
}

std::string_view

一、std::string_view:轻量字符串视图(C++17 起)

简介

std::string_view 是一个非拥有型的只读字符串引用,不分配内存、不复制数据,适用于传参和高效处理子串。

关键特性

  • 快速,无拷贝(零开销)
  • 支持与 std::string 类似的操作(如 substr, find
  • 生命周期由原始字符串控制,不能跨作用域使用

示例:

cpp 复制代码
#include <iostream>
#include <string>
#include <string_view>

void greet(std::string_view name) {
    std::cout << "Hello, " << name << std::endl;
}

int main() {
    std::string full = "Alice Wonderland";
    std::string_view sv = full.substr(0, 5);  // "Alice"
    greet(sv);
}

用于高性能接口设计,可避免大量 string 拷贝。


二、性能优化技巧(std::string)

1. 减少重复构造

避免 string 频繁复制、构造,尽量使用引用或 std::string_view

cpp 复制代码
void process(const std::string& s);  // 优于传值

2. 预分配容量 .reserve()

避免频繁扩容导致的内存复制:

cpp 复制代码
std::string data;
data.reserve(1024);  // 提前分配空间,避免多次 realloc

3. 避免 += 拼接过多次(会触发多次 reallocation)

可改用:

cpp 复制代码
std::ostringstream oss;
oss << "Name: " << name << ", Age: " << age;
std::string result = oss.str();

三、Unicode / UTF-8 字符处理(中文、Emoji等)

C++ std::string 本身对字符集不做解释,只是按字节存储。

示例:
cpp 复制代码
std::string str = "你好";  // 实际为 6 个字节,不是 2 个字符
std::cout << str.length();  // 输出:6

推荐处理 UTF-8 的库:

特点
utf8cpp 轻量、纯头文件库
ICU(Intl Components for Unicode) 功能强大,适用于多语言、排序等
C++20 char8_t / std::u8string 新的 UTF-8 字符类型(现代C++,但库支持有限)

使用 utf8cpp 示例(读取 UTF-8 字符):

cpp 复制代码
#include <utf8.h>
std::string s = "你好世界";
auto it = s.begin();
while (it != s.end()) {
    uint32_t cp = utf8::next(it, s.end());
    std::cout << std::hex << cp << " ";
}

四、常见误区与调试建议

1. c_str() 返回的是 const char*,不能修改其内容

cpp 复制代码
char* p = s.c_str();  // 编译器可能允许,但是 UB(未定义行为)

2. 不要返回局部 string_view

cpp 复制代码
std::string_view get_name() {
    std::string tmp = "Tom";
    return tmp;  // ❌ tmp 销毁后 string_view 悬空
}

调试建议

  • 使用 .data() + .size() 查看原始字节内容
  • .substr() 替代手动字符切片(更安全)
  • 使用 std::u32string 处理 Unicode(每字符固定宽度)

总结:适用场景对比

功能需求 建议使用
动态字符串、读写操作 std::string
只读子串、传参 std::string_view
跨平台 Unicode 处理 utf8cppICU
UTF-16 / UTF-32 字符 std::u16string, std::u32string

相关推荐
blasit7 小时前
笔记:Qt C++建立子线程做一个socket TCP常连接通信
c++·qt·tcp/ip
AI软著研究员7 小时前
程序员必看:软著不是“面子工程”,是代码的“法律保险”
算法
FunnySaltyFish7 小时前
什么?Compose 把 GapBuffer 换成了 LinkBuffer?
算法·kotlin·android jetpack
颜酱8 小时前
理解二叉树最近公共祖先(LCA):从基础到变种解析
javascript·后端·算法
地平线开发者1 天前
SparseDrive 模型导出与性能优化实战
算法·自动驾驶
董董灿是个攻城狮1 天前
大模型连载2:初步认识 tokenizer 的过程
算法
地平线开发者1 天前
地平线 VP 接口工程实践(一):hbVPRoiResize 接口功能、使用约束与典型问题总结
算法·自动驾驶
罗西的思考1 天前
AI Agent框架探秘:拆解 OpenHands(10)--- Runtime
人工智能·算法·机器学习
HXhlx1 天前
CART决策树基本原理
算法·机器学习
Wect1 天前
LeetCode 210. 课程表 II 题解:Kahn算法+DFS 双解法精讲
前端·算法·typescript