java中能用多少字符_JAVA性能优化中,字符串的使用你了解多少?快来了解一下吧...

本文介绍了C++ std::string类模板的使用优化,包括字符串动态增长的原理、内存管理以及COW(Copy-On-Write)策略。在C++11之后,引入了右值引用和移动语义,进一步减轻了复制的开销。通过理解这些机制,开发者可以更有效地使用和管理字符串,提升程序性能。
摘要由CSDN通过智能技术生成

C++ 的 std::string 类模板是 C++ 标准库中使用最广泛的特性之一。那么关于优化字符串的使用你知道多少呢?下面跟编程小达人一起来学习一下吧。

字符串在概念上很简单,但是想要实现高效的字符串却非常微妙。为了能够跟上 C++ 标准的变化,std::string 的行为也在不断地变化。这意味着,在 C++98 编译器中实现的符合标准的 std::string 的行为可能与在 C++11 之后实现的 std::string 的行为是不同的。

6f913d164b57adaf94cf17500cf69684.png

字符串之所以使用起来很方便,是因为它们会为了保存内容而自动增长。相比之下,C 的库函数(strcat()、strcpy() 等)工作于固定长度的字符数组上。

为了实现这种灵活性,字符串被设计为动态分配的。相比于 C++ 的大多数其他特性,动态分配内存耗时耗力。因此无论如何,字符串都是性能优化热点。

35be7fe9f85fb14af62861671929728f.png

当一个字符串变量超出了其定义范围或是被赋予了一个新的值后,动态分配的存储空间会被自动释放。与下面这段代码展示的需要为动态分配的 C 风格的字符数组手动释放内存相比,这样无疑方便了许多。

char* p = (char*) malloc(7); strcpy(p, "string"); ... free(p);

尽管如此,但字符串内部的字符缓冲区的大小仍然是固定的。任何会使字符串变长的操作,如在字符串后面再添加一个字符或是字符串,都可能会使字符串的长度超出它内部的缓冲区的大小。当发生这种情况时,操作会从内存管理器中获取一块新的缓冲区,并将字符串复制到新的缓冲区中。

118965b0c75162de1371666502d101c2.png

在赋值语句和表达式中,字符串的行为与值是一样的。可以将一个新值赋予给一个变量,但是改变这个变量并不会改变这个值。例如:

int i,j; i = 3; // i的值是3 j = i; // j的值也是3 i = 5; // i的值现在是5,但是j的值仍然是3

将一个字符串赋值给另一个字符串的工作方式是一样的,就仿佛每个字符串变量都拥有一份它们所保存的内容的私有副本一样:

std::string s1, s2; s1 = "hot"; // s1是"hot" s2 = s1; // s2是"hot" s1[0] = 'n'; // s2仍然是"hot",但s1变为了"not"

由于字符串就是值,因此字符串表达式的结果也是值。如果你使用 s1 = s2 + s3 + s4; 这条语句连接字符串,那么 s2 + s3 的结果会被保存在一个新分配的临时字符串中。连接 s4 后的结果则会被保存在另一个临时字符串中。这个值将会取代 s1 之前的值。接着,为第一个临时字符串和 s1 之前的值动态分配的内存将会被释放。这会导致多次调用内存管理器。

5bfb1158fdac499fb79fa1111740e104.png

有一种被称为“写时复制”的著名的编程惯用法,它可以让对象与值具有同样的表现,但是会使复制的开销变得非常大。在 C++ 文献中,它被简称为 COW。

在 COW 的字符串中,动态分配的内存可以在字符串间共享。每个字符串都可以通过引用计数知道它们是否使用了共享内存。当一个字符串被赋值给另一个字符串时,所进行的处理只有复制指针以及增加引用计数。任何会改变字符串值的操作都会首先检查是否只有一个指针指向该字符串的内存。

如果多个字符串都指向该内存空间,所有的变值操作(任何可能会改变字符串值的操作)都会在改变字符串值之前先分配新的内存空间并复制字符串:

COWstring s1, s2; s1 = "hot"; // s1是"hot" s2 = s1; // s2是"hot"(s1和s2指向相同的内存) s1[0] = 'n';// s1会在改变它的内容之前将当前内存空间中的内容复制一份 // s2仍然是"hot",但s1变为了"not"

d7f9b962061e07b37f9567dbebe0bc89.png

以上就是今天为大家分享的关于优化字符串使用的方法,你学会了吗?在 C++11 及之后的版本中,随着“右值引用”和“移动语义”的出现,使用它们可以在某种程度上减轻复制的负担。如果一个函数使用“右值引用”作为参数,那么当实参是一个右值表达式时,字符串可以进行轻量级的指针复制,从而节省一次复制操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值