为啥在 GCC 5.1 中仍然启用 COW std::string 优化?
Posted
技术标签:
【中文标题】为啥在 GCC 5.1 中仍然启用 COW std::string 优化?【英文标题】:Why is COW std::string optimization still enabled in GCC 5.1?为什么在 GCC 5.1 中仍然启用 COW std::string 优化? 【发布时间】:2015-07-05 08:39:58 【问题描述】:根据 GCC 5 发布更改页面 (https://gcc.gnu.org/gcc-5/changes.html):
默认启用新的 std::string 实现,使用小字符串优化而不是写时复制引用计数
我决定检查一下,写了一个简单的程序:
int main()
std::string x"blah";
std::string y = x;
printf("0x%X\n", x.c_str());
printf("0x%X\n", y.c_str());
x[0] = 'c';
printf("0x%X\n", x.c_str());
printf("0x%X\n", y.c_str());
结果是:
0x162FC38
0x162FC38
0x162FC68
0x162FC38
请注意,x.c_str() 指针在 x[0] = 'c' 之后发生了变化。这意味着内部缓冲区在写入时被复制。因此,COW 似乎仍在工作。为什么?
我在 Ubuntu 上使用 g++ 5.1.0。
【问题讨论】:
我猜你的发行版上的 gcc 配置不同于默认配置以保持 ABI 兼容性。 你是对的。我用 -D _GLIBCXX_USE_CXX11_ABI 编译它,现在它按预期工作(没有 COW 也没有动态内存分配,所以很明显 SSO 正在使用中)。 【参考方案1】:某些发行版故意偏离 FSF GCC 选择以默认使用新的 ABI。 Here's an explanation of why Fedora 22 deviates from upstream GCC like that.总之:
在一个程序中,最好不要将新旧 ABI 混在一起,而是选择一个并坚持下去。如果程序的某个部分采用与程序的另一部分不同的类型的内部表示,事情就会中断。
因此,如果使用任何使用旧 C++ ABI 的 C++ 库,那么使用该库的程序也应该使用旧 C++ ABI。
因此,如果使用任何使用 GCC 4.9 或更早版本构建的 C++ 库,则使用该库的程序也应该使用旧的 C++ ABI。
Fedora 22 仍然提供(或提供?)大量使用 GCC 4.9 构建的库,因为在 Fedora 22 发布之前没有足够的时间使用 GCC 5.1 重新构建它们。为了允许程序使用这些库,GCC 默认切换到旧的 ABI。
据我所知,GCC 5 还不是 Ubuntu 中的默认编译器(但很快就会成为),所以如果它作为额外安装提供,那么来自 Fedora 的相同参数也适用于 Ubuntu。
【讨论】:
以上是关于为啥在 GCC 5.1 中仍然启用 COW std::string 优化?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 std::map emplace 需要 gcc 上的复制构造函数?
为啥 std::array::size constexpr 具有简单类型(int,double,...)而不是 std::vector (GCC)?
为啥在将 msys gcc 从 9.2 更新到 10.1.0 后我的所有 std 命名空间都损坏了
为啥 MinGW 中仍然没有 std::thread、std::promise 和 std::future? win32中promise和futures的替代方案是啥?