Mic*_*kis 14 c++ string g++ internals
(免责声明:我不知道C++标准对此有何看法......我知道,我很可怕)
在非常大的字符串上操作时,我注意到std :: string正在使用copy-on-write.我设法编写了可以重现观察到的行为的最小循环,例如,下面的循环运行得非常快:
#include <string>
using std::string;
int main(void) {
string basestr(1024 * 1024 * 10, 'A');
for (int i = 0; i < 100; i++) {
string a_copy = basestr;
}
}
Run Code Online (Sandbox Code Playgroud)
当在循环体中添加写入时a_copy[1] = 'B';,显然发生了实际复制,程序以0.3s而不是几毫秒运行.100次写入减慢了大约100次.
但后来很奇怪.我的一些字符串没有被写入,只是从中读取,而这并没有反映在执行时间中,这几乎与字符串上的操作数成正比.通过一些挖掘,我发现只是从字符串读取仍然给我性能命中,所以它让我假设GNU STL字符串正在使用copy-on-read(?).
#include <string>
using std::string;
int main(void) {
string basestr(1024 * 1024 * 10, 'A');
for (int i = 0; i < 100; i++) {
string a_copy = basestr;
a_copy[99]; // this also ran in 0.3s!
}
}
Run Code Online (Sandbox Code Playgroud)
在我的发现中陶醉了一段时间之后,我发现从基础字符串中读取(带有operator [])对于整个玩具程序来说也需要0.3秒.我对此并不是100%舒服.STL字符串是否确实是可读写的,或者它们是否允许写入时复制?我被认为operator []有一些保护措施可以防止一个人保留它返回的引用并稍后写入它; 这是真的吗?如果没有,真正发生了什么?如果有人可以指出C++标准中的某些相关部分,那也值得赞赏.
作为参考,我正在使用g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3和GNU STL.
ken*_*ytm 14
C++不区分operator[]用于读取和写入,而只区分operator[]for const对象和可变(非const)对象.由于a_copy是可变的,因此operator[]将选择mutable ,这会强制复制,因为该运算符返回(可变)引用.
如果效率是一个问题,你可以强制a_copy转换const string为强制使用的const版本operator[],这将不会复制内部缓冲区.
char f = static_cast<const string>(a_copy)[99];
Run Code Online (Sandbox Code Playgroud)
CB *_*ley 13
C++标准不禁止或强制要求写入时复制或任何其他实现细节std::string.只要满足语义和复杂性要求,实现就可以选择它喜欢的任何实现策略.
请注意,operator[]非const字符串实际上是一个"写"操作,因为它返回一个引用,该引用可用于在任何点修改字符串,直到下一个操作变异字符串.此类修改不应影响任何副本.
你有没有尝试过分析这两个中的一个?
const string a_copy = basestr;
a_copy[99];
Run Code Online (Sandbox Code Playgroud)
要么
string a_copy = basestr;
const std::string& a_copy_ref = a_copy;
a_copy_ref[99];
Run Code Online (Sandbox Code Playgroud)