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

dre*_*rbs 10 c++ undefined-behavior type-punning c++11

Facebook的fbstring_core类使用中所描述的"小字符串优化" 这次谈话,其中的类的数据成员的存储-一Char*,sizecapacity-将被重新用于存储字符数据字符串是否足够小.用于区分这些情况的标志位位于"存储器的最右边的字符"中.我的问题是,是否通过bytes_union成员访问这些位(实际上从未编写过)是否构成了C++ 11标准的未定义行为?访问非活动联盟成员和未定义行为的答案表明它是.

以下摘录包含这些成员的声明以及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_;
    };
Run Code Online (Sandbox Code Playgroud)

看起来这个实现依赖于使用"类型双关语"来访问实际上可能是size_t capacity_成员一部分的字节.从问题的答案上面链接,据我了解,这在C99中定义的行为,而不是在C++ 11?

Joh*_*nck 13

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

reinterpret_cast<const char*>(this)[sizeof(*this) - 1]
Run Code Online (Sandbox Code Playgroud)

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