SU3*_*SU3 15 c++ memory string optimization gcc
大多数std::string实现(包括GCC)使用小字符串优化.例如,有一个答案在讨论这个问题.
今天,我决定检查我编译的代码中的字符串在什么时候被移动到堆中.令我惊讶的是,我的测试代码似乎表明根本没有发生小的字符串优化!
码:
#include <iostream>
#include <string>
using std::cout;
using std::endl;
int main(int argc, char* argv[]) {
std::string s;
cout << "capacity: " << s.capacity() << endl;
cout << (void*)s.c_str() << " | " << s << endl;
for (int i=0; i<33; ++i) {
s += 'a';
cout << (void*)s.c_str() << " | " << s << endl;
}
}
Run Code Online (Sandbox Code Playgroud)
输出g++ test.cc && ./a.out是
capacity: 0
0x7fe405f6afb8 |
0x7b0c38 | a
0x7b0c68 | aa
0x7b0c38 | aaa
0x7b0c38 | aaaa
0x7b0c68 | aaaaa
0x7b0c68 | aaaaaa
0x7b0c68 | aaaaaaa
0x7b0c68 | aaaaaaaa
0x7b0c98 | aaaaaaaaa
0x7b0c98 | aaaaaaaaaa
0x7b0c98 | aaaaaaaaaaa
0x7b0c98 | aaaaaaaaaaaa
0x7b0c98 | aaaaaaaaaaaaa
0x7b0c98 | aaaaaaaaaaaaaa
0x7b0c98 | aaaaaaaaaaaaaaa
0x7b0c98 | aaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
0x7b0d28 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Run Code Online (Sandbox Code Playgroud)
我猜测较大的第一个指针,即0x7fe405f6afb8是一个堆栈指针,而其他指针指向堆.多次运行会产生相同的结果,因为第一个地址总是很大,而其他地址都比较小; 确切的值通常不同.较小的地址始终遵循2分配方案的标准功率,例如0x7b0c38列出一次,然后0x7b0c68列出一次,然后0x7b0c38两次,然后是0x7b0c684次,然后是0x7b0c988次,等等.
在阅读霍华德的答案后,使用64位机器,我希望看到前22个字符打印的地址相同,然后才能看到它的变化.
我错过了什么吗?
另外,有趣的是,如果我使用-O(在任何级别)编译,我会0x6021f8在第一种情况下获得一个常量小指针值,而不是大值,并且0x6021f8无论我运行程序多少次,这都不会改变.
产量g++ -v:
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/foo/bar/gcc-6.2.0/gcc/libexec/gcc/x86_64-redhat-linux/6.2.0/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../gcc-6.2.0/configure --prefix=/foo/bar/gcc-6.2.0/gcc --build=x86_64-redhat-linux --disable-multilib --enable-languages=c,c++,fortran --with-default-libstdcxx-abi=gcc4-compatible --enable-bootstrap --enable-threads=posix --with-long-double-128 --enable-long-long --enable-lto --enable-__cxa_atexit --enable-gnu-unique-object --with-system-zlib --enable-gold
Thread model: posix
gcc version 6.2.0 (GCC)
Run Code Online (Sandbox Code Playgroud)
gsa*_*ras 21
你的一面旗帜是:
--with-default-libstdcxx-abi=gcc4-compatible
Run Code Online (Sandbox Code Playgroud)
和GCC4并没有支持小串optimzation.
GCC5开始支持它.isocpp说:
默认情况下,使用小字符串优化而不是写入时复制引用计数来启用std :: string的新实现.
这支持我的主张.
此外,探索std :: string提到:
正如我们所看到的,较旧的libstdc ++实现了写时复制,因此它们不利用小对象优化是有意义的.
当GCC5进场时,他会改变背景.