FBString的小字符串优化是否依赖于未定义的行为?

时间:2017-08-26 22:29:27

标签: c++ c++11 undefined-behavior type-punning

Facebook的fbstring_core课程使用"小字符串优化"在this talk中描述的,其中存储了该类'如果字符串足够小,数据成员 - Char*sizecapacity将重新用于存储字符数据。用于区分这些情况的标志位位于存储"的最右边的字符串中。我的问题是,是否通过bytes_联合成员访问这些位(从未实​​际编写过)是否构成了 C ++ 11 标准的未定义行为? Accessing inactive union member and undefined behavior?的答案表明它是。

以下摘录包含这些成员的声明以及用于确定此优化是否生效的category()成员函数。

    typedef uint8_t category_type;

    enum class Category : category_type {
      isSmall = 0,
      isMedium = kIsLittleEndian ? 0x80 : 0x2,
      isLarge = kIsLittleEndian ? 0x40 : 0x1,
    };

    Category category() const {
      // works for both big-endian and little-endian
      return static_cast<Category>(bytes_[lastChar] & categoryExtractMask);
    }

    struct MediumLarge {
      Char * data_;
      size_t size_;
      size_t capacity_;

      size_t capacity() const {
        return kIsLittleEndian
          ? capacity_ & capacityExtractMask
          : capacity_ >> 2;
      }

      void setCapacity(size_t cap, Category cat) {
        capacity_ = kIsLittleEndian
            ? cap | (static_cast<size_t>(cat) << kCategoryShift)
            : (cap << 2) | static_cast<size_t>(cat);
      }
    };

    union {
      uint8_t bytes_[sizeof(MediumLarge)]; // For accessing the last byte.
      Char small_[sizeof(MediumLarge) / sizeof(Char)];
      MediumLarge ml_;
    };

这个实现似乎依赖于使用&#34;类型惩罚&#34;访问可能实际上属于size_t capacity_成员的字节。从上面链接的问题的答案,我收集到这个在C99中定义的行为,但不是在C ++ 11中?

1 个答案:

答案 0 :(得分:11)

这不仅仅是UB,这是非常不必要的,因为bytes_的唯一用途似乎是用于读取this的最后一个字节,这可以在没有UB的情况下完成:< / p>

reinterpret_cast<const char*>(this)[sizeof(*this) - 1]

这要归功于C ++中的特殊豁免,它允许将对象重新解释为char数组。