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

相关推荐
Jina AI24 分钟前
回归C++: 在GGUF上构建高效的向量模型
人工智能·算法·机器学习·数据挖掘·回归
Coovally AI模型快速验证29 分钟前
YOLO、DarkNet和深度学习如何让自动驾驶看得清?
深度学习·算法·yolo·cnn·自动驾驶·transformer·无人机
luoqice36 分钟前
linux下找到指定目录下最新日期log文件
linux·算法
努力努力再努力wz1 小时前
【c++深入系列】:万字详解模版(下)
java·c++·redis
楽码1 小时前
底层技术SwissTable的实现对比
数据结构·后端·算法
fffcccc11121 小时前
初级背包问题,层层剖析为什么这样做。最好需要自己推演一遍。
算法
林开落L1 小时前
库的制作与原理
linux·开发语言·动静态库·库的制作
m0_480502641 小时前
Rust 入门 泛型和特征-特征对象 (十四)
开发语言·后端·rust
瓦特what?2 小时前
关于C++的#include的超超超详细讲解
java·开发语言·数据结构·c++·算法·信息可视化·数据挖掘
祁同伟.2 小时前
【C++】动态内存管理
开发语言·c++