为了账号安全,请及时绑定邮箱和手机立即绑定

libc ++中短字符串优化的机制是什么?

libc ++中短字符串优化的机制是什么?

C++
杨__羊羊 2019-08-26 17:21:48
libc ++中短字符串优化的机制是什么?我想更详细地了解它在实践中是如何工作的,特别是在libc ++实现中:为了符合SSO资格,字符串有多短?这取决于目标架构吗?在访问字符串数据时,实现如何区分短字符串和长字符串?它m_size <= 16是一个简单的,还是一个标志,是其他成员变量的一部分?(我想这m_size或其中的一部分也可能用于存储字符串数据)。我专门针对libc ++问了这个问题,因为我知道它使用SSO,甚至在libc ++主页上也提到过。以下是查看来源后的一些观察结果:libc ++可以使用两个稍微不同的字符串类内存布局进行编译,这由_LIBCPP_ALTERNATE_STRING_LAYOUT标志控制。这两种布局还区分了little-endian和big-endian机器,这些机器总共留下了4种不同的变体。我将在下面的内容中假设“正常”布局和小端。假设进一步size_type是4个字节并且value_type是1个字节,这就是字符串的前4个字节在内存中的样子:// short string: (s)ize and 3 bytes of char (d)atasssssss0;dddddddd;dddddddd;dddddddd       ^- is_long = 0// long string: (c)apacityccccccc1;cccccccc;cccccccc;cccccccc       ^- is_long = 1由于短字符串的大小在高7位,因此在访问它时需要移位:size_type __get_short_size() const {     return __r_.first().__s.__size_ >> 1;}类似地,长字符串容量的getter和setter用于__long_mask解决这个问题is_long。我仍在寻找我的第一个问题的答案,即__min_cap短字符串的容量对不同的架构有什么价值?
查看完整描述

2 回答

?
冉冉说

TA贡献1877条经验 获得超1个赞


在libc中++实现有点复杂,我会忽略它的替代性设计,并假设小端计算机:


template <...>

class basic_string {

/* many many things */


    struct __long

    {

        size_type __cap_;

        size_type __size_;

        pointer   __data_;

    };


    enum {__short_mask = 0x01};

    enum {__long_mask  = 0x1ul};


    enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ?

                      (sizeof(__long) - 1)/sizeof(value_type) : 2};


    struct __short

    {

        union

        {

            unsigned char __size_;

            value_type __lx;

        };

        value_type __data_[__min_cap];

    };


    union __ulx{__long __lx; __short __lxx;};


    enum {__n_words = sizeof(__ulx) / sizeof(size_type)};


    struct __raw

    {

        size_type __words[__n_words];

    };


    struct __rep

    {

        union

        {

            __long  __l;

            __short __s;

            __raw   __r;

        };

    };


    __compressed_pair<__rep, allocator_type> __r_;

}; // basic_string

注意:__compressed_pair基本上是针对空基优化而优化的一对,又称template <T1, T2> struct __compressed_pair: T1, T2 {};; 对于所有意图和目的,你可以认为它是一个常规对。它的重要性刚刚出现,因为它std::allocator是无国籍的,因此是空的。


好的,这是相当原始的,所以让我们检查一下这些机制!在内部,许多函数将调用__get_pointer()自己调用__is_long以确定字符串是否使用__long或__short表示:


bool __is_long() const _NOEXCEPT

    { return bool(__r_.first().__s.__size_ & __short_mask); }


// __r_.first() -> __rep const&

//     .__s     -> __short const&

//     .__size_ -> unsigned char

说实话,我不太确定这是标准C ++(我知道最初的子序列规定,union但不知道它是如何与匿名联合和别名一起抛出的),但是允许标准库利用定义的实现无论如何。


查看完整回答
反对 回复 2019-08-26
  • 2 回答
  • 0 关注
  • 641 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号