深入探究 C++ 字符串

在上一篇文章中我们聊到了 C 语言字符串的相关内容。比如 C 字符串字面量是只读数据------不可修改。如果需要修改只能将只读数据拷贝到字符数组中------char *。

C++ 的 STL 提供了一个字符串类------std::string 简化了大量的字符串操作,而且同样也支持 C 的字符串字面量来初始化,比如下面这样:

c 复制代码
std::string str = "C and C++ Strings"; 

这篇文章,我们接着上一篇文章的内容,继续探讨下面几个关于std::string 的问题:

  1. C++ string 在通过字符串字面量初始化时有拷贝发生吗?
  2. C++ string 在与其它字符串字面量拼接(+操作)时有拷贝发生吗?

std::string 类的初始化

首先 std::string 是可变量,也就说我们可以增加、缩减或者修改内容。而 C 字符串字面量都不可修改的,因此我们不难推测出用 C 字符串字面量初始化 std::string 类时也会有拷贝发生。在上一篇文章中我们举了这样一个例子:

c 复制代码
char[] str = "C and C++ Strings"; 

其中隐含了一个点------用栈空间来储存该字符数组。同样我们也可以用堆空间来存储,像下面这样:

c 复制代码
  const int str_len = 100;
  char *ptr = (char *)malloc(str_len);
  if (ptr == NULL) {
    return;
  }
  strcpy(ptr, "C and C++ strings");
  printf("string: %s, length: %ld", ptr, strlen(ptr));
  free(ptr);

std::string 其实就是把上面的两种处理重载成了一个赋值运算符,并在内部封装了一个字符数组。

因为栈空间有限不可能全部使用栈空间存储字符串,堆空间虽然理论上可以无限大,但是频繁申请小内存也会导致内存碎片问题。因此,在 GCC 和 Clang 编译器的 STL 实现中,如果字面量长度小于等于 16(包含终止符)则会在栈上储存,否则在堆上存储。

std::string 的拼接

使用 std::string 的过程中,我们也会经常用 + 来拼接字符串,像下面这样:

c 复制代码
std::string str = "C and C++";
std::string str1 = str + " strings";

我们不妨大胆推测一下。

因为 std::string 是可修改的,拼接字符串字面量务必需要拷贝到 std::string 内部的字符数组中。根据 GCC 和 Clang 针对小字符串的优化,我们也可以推测,如果两个字符串的长度小于等于 16 则存放在栈中,否则储存在堆中。

那怎么验证呢?

我们可以重载 new 运算符,增加日志信息。这样每次使用 new 申请堆内存时便有日志打印。

c 复制代码
void* operator new(size_t count) {
  std::cout << "\tAllocate " << count << " bytes\n";
  return malloc(count);
}

剩下的就交给大家,写代码验证一下吧。如果有问题,欢迎到评论区讨论。

思考问题

  1. 怎样避免字面量初始化 std::string 的拷贝呢?

参考资料

C++17 -- Avoid Copying with std::string_view -- MC++ BLOG (modernescpp.com)

相关推荐
一晌小贪欢11 分钟前
Python基础:第 09 篇 · while 循环:重复直到不满足
开发语言·c++·python·数据可视化·面向对象·python办公
xiaoye-duck44 分钟前
《C++ 项目:手写大模型接入 SDK》LLMManager架构设计与实现
开发语言·网络·c++·语言模型
一条大祥脚1 小时前
CuTe 与 CuTe DSL:从 C++ 模板元编程到 Python DSL 的 GPU 编程演进
开发语言·c++·python·cutlass·cute·cute dsl
·present·1 小时前
CSAPP(lecture 13_02 Linking)
c语言·c++
FRing032 小时前
vue2干货总结8(路由模块封装、router-link、声明式导航、路由重定向、编程式导航)
开发语言·前端·vue.js·vue2
旖旎夜光2 小时前
【C++ 基础入门】C++ 多态(上):虚函数、重写、override/final 与抽象类
开发语言·c++·笔记·学习
starzy19902 小时前
深入理解Scala嵌套函数:作用域封装之道
开发语言·scala
Sakura_j_h_2 小时前
从零写一个 MCP stdio Server:用 Python 校验博客文章格式
开发语言·python·自动化·ai工具·mcp·json-rpc
青少儿编程课堂4 小时前
蓝桥杯青少组图形化 STEMA 省考(报名倒计时·11/22开考)+ 全国青少年信息素养大赛 2026—2027赛季 + 电子学会图形化考级:校园华容道大闯关
c++·python·算法·bfs·信息学竞赛
白杨尚青4 小时前
C++进阶篇(五):红黑树——四条规则、三种插入情况与旋转变色
开发语言·数据结构·c++·stl·红黑树·平衡二叉树