在 C++ 标准中,std:string
遵循指数增长策略,因此我认为在连接期间字符串的 capacity()
总是会在必要时增加。但是,当我测试test.cpp
时,我发现在for-loop中,只有每两次 capacity()
才会收缩在分配期间返回到 length()
。
为什么这种行为不取决于字符串的长度,而是取决于我更改字符串的频率?是某种优化吗?
以下代码使用 g++ -std=c++11
进行了测试。
测试.cpp:
#include <iostream>
int main(int argc, char **argv) {
std::string s = "";
for (int i = 1; i <= 1000; i++) {
//s += "*";
s = s + "*";
std::cout << s.length() << " " << s.capacity() << std::endl;
}
return 0;
}
输出将是这样的:
1 1
2 2
3 4
4 4
5 8
6 6 // why is capacity shrunk?
7 12
8 8 // and again?
9 16
10 10 // and again?
11 20
12 12 // and again?
13 24
14 14 // and again?
15 28
16 16 // and again?
17 32
...
996 996
997 1992
998 998 // and again?
999 1996
1000 1000 // and again?
最佳答案
当你这样做时:
s = s + "*";
你在做两件不同的事情:制作一个新的临时字符串,由连接到内容 s
末尾的 "*"
组成,然后复制分配s
的新字符串。
收缩的不是+
,而是=
。当从一个字符串复制分配到另一个字符串时,没有理由复制容量,只复制实际使用的字节数。
您注释掉的代码执行此操作:
s += "*";
... 只做一件事,将 "*"
附加到 s
的末尾。因此,没有地方可以进行“优化”(如果发生了,那将是一种悲观,破坏了指数增长的全部目的)。
关于c++字符串容量在复制分配期间发生变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24399519/