【问题标题】:Test whether libstdc++'s version uses a C++11-compliant std::string测试 libstdc++ 的版本是否使用符合 C++11 的 std::string
【发布时间】:2015-12-19 22:12:20
【问题描述】:

我正在编写一些 C++11 代码,这些代码对 std::string 的性质进行了假设,这些假设是有效的,但代表了 C++11 中已更改的行为。在早期,libstdc++ 的basic_string 实现符合 98/03 要求,但不符合更严格的 C++11 要求。

据我了解,libstdc++ 已经解决了 basic_string 周围的问题。问题是人们使用的许多版本的库都没有实现这个修复。而且我的代码可能会以许多令人不快的方式默默地失败。

如果用户尝试针对那些不符合标准的 libstdc++ 版本编译我的库,我希望触发static_assert。如何检测版本,同样重要的是,我应该寻找哪个版本?

【问题讨论】:

  • 你能说出你的假设吗?
  • 我相信即使在 C++03 中也是如此。 COW 应该保留这个属性。
  • @Puppy:对不起,我说错了。最好只是look here。类似的东西。
  • @TobiasLangner:因为我的大多数用户将编译我的,而不是我的测试。
  • @Tobias:你假设他的库实际上一些一次性初始化。

标签: c++ c++11 stdstring libstdc++


【解决方案1】:

在 GCC 5 (Runtime Library Section of the changelog) 中引入了新的符合 C++11 的 std::string 和新的(双)ABI。

_GLIBCXX_USE_CXX11_ABI 决定是使用旧 ABI 还是新 ABI,所以只需检查它:

#if _GLIBCXX_USE_CXX11_ABI

当然,这仅适用于 libstdc++。

【讨论】:

    【解决方案2】:
    #include <string>
    
    static_assert(sizeof(std::string) != sizeof(void*), "using ref-counted string");
    
    int
    main()
    {
    }
    

    演示:http://melpon.org/wandbox/permlink/P8LB79Cy6ASZlKuV

    此测试利用std::string 的所有已知 std::lib 实现的内部工作原理,尤其是 gcc 的实现。

    gcc 的引用计数string 由一个指向动态分配结构的指针组成,该结构保存字符串的大小、容量、引用计数和数据。 Scott Meyers 对 Effective STL 中的字符串实现做了一个很好的总结,在 2001 年的时间框架内是准确的。我相信(我可能弄错了)那本书第 15 项中的“实现 C”是 gcc 的 std::string。

    对于短字符串实现(C++11 几乎强制要求),string 不能再由堆栈上的单个指针组成。 Scott 的实现 D 是我们第一次看到那个时代的短字符串实现。这是 VS/Dinkumware stringsizeof(string) 本身将包含一些数据缓冲区来保存没有分配的字符串数据。

    人们可以通过这个简短的程序了解不同的实现正在做什么:

    #include <iostream>
    #include <string>
    
    int
    main()
    {
        std::string s;
        std::cout << "word size is           " << sizeof(void*)/sizeof(char) << '\n';
        std::cout << "sizeof string is       " << sizeof(s) << '\n';
        std::cout << "short string buffer is " << s.capacity() << '\n';
    }
    

    这会打印出字长,通常为 4 或 8(32 位 / 64 位),因为至少有一个实现 (libc++) 在此硬件功能上更改了其特性。然后它打印出sizeof(string),它将是字长的倍数,然后是空的stringcapacity(),如果它存在,它将是短字符串缓冲区的大小。

    这是一个有些不完整的调查:

    gcc/libstdc++ 4.8
    
    word size is           8
    sizeof string is       8
    short string buffer is 0
    

    gcc/libstdc++ 5.2
    
    word size is           8
    sizeof string is       32
    short string buffer is 15
    

    clang/libc++ -arch i386 OS X
    
    word size is           4
    sizeof string is       12
    short string buffer is 10
    

    clang/libc++ -arch x86_64 OS X
    
    word size is           8
    sizeof string is       24
    short string buffer is 22
    

    VS-2015
    
    word size is           4
    sizeof string is       24
    short string buffer is 15
    

    在这次调查中,只有 gcc/libstdc++ 4.8 显然没有使用短字符串优化。只有 gcc/libstdc++ 4.8 有sizeof(string) == 1 word。这实际上是本次调查中唯一使用引用计数的实现。

    总而言之,这个针对 libstdc++ 的std::string 的测试是不可移植的。但根据规范,它不一定是。我们可以利用已知的 gcc 在这一领域的发展历史。规范(问题)说它只需要在 gcc 的 libstdc++ 上工作。

    【讨论】:

    • 您能简要解释一下为什么这样做会奏效吗? COW 字符串是否只有一个 void*(私有)数据成员,当然没有虚函数?
    • 谢谢,很好的解释。
    • 为了扩展调查,VS-2013 字符串与 VS-2015 具有相同的结构。在 VS-2010 中,字符串的字数更大(由于没有优化零大小的 std::allocator)。我为不同标准库的 64 位版本整理了一个 summary table,其中还包括其他细节,例如增长策略。
    猜你喜欢
    • 1970-01-01
    • 2018-10-04
    • 2011-03-01
    • 2014-02-19
    • 2014-02-21
    • 2016-11-25
    • 2014-04-27
    • 2016-04-16
    • 2011-08-29
    相关资源
    最近更新 更多