为什么在GCC 5.1中仍然启用了COW std :: string优化?

5
根据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。

6
我猜测你的发行版上的gcc编译器配置与默认配置不同,是为了保持ABI兼容性。 - Stephan Dollberg
你是对的。我使用了 -D _GLIBCXX_USE_CXX11_ABI 编译它,现在它按预期工作(没有 COW 和动态内存分配,因此明显使用了 SSO)。 - rubix_addict
1个回答

10

一些发行版有意偏离FSF GCC的选择,将默认设置为新ABI。 这里解释了为什么Fedora 22会这样偏离上游GCC。 简而言之:

在程序中,最好不要混合旧的和新的ABI,而是选择一个并坚持使用它。如果程序的某个部分假定类型的内部表示与程序的另一部分不同,则会导致问题。

因此,如果使用任何使用旧C++ ABI的C++库,则使用该库的程序也应使用旧C++ ABI。

因此,如果使用任何使用GCC 4.9或更早版本构建的C++库,则使用该库的程序也应使用旧C++ ABI。

Fedora 22仍然提供(或曾经提供)许多使用GCC 4.9构建的库,因为在Fedora 22发布之前没有足够的时间将它们全部重新构建为GCC 5.1。为了允许程序使用这些库,GCC默认设置为旧的ABI。

据我所知,Ubuntu目前还没有将GCC 5设为默认编译器(不过很快会这样),因此如果它作为额外安装提供的话,Fedora中相同的参数也适用于Ubuntu。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接