Facebook的fbstring_core课程使用"小字符串优化"在this talk中描述的,其中存储了该类'如果字符串足够小,数据成员 - Char*
,size
和capacity
将重新用于存储字符数据。用于区分这些情况的标志位位于存储"的最右边的字符串中。我的问题是,是否通过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中?
答案 0 :(得分:11)
这不仅仅是UB,这是非常不必要的,因为bytes_
的唯一用途似乎是用于读取this
的最后一个字节,这可以在没有UB的情况下完成:< / p>
reinterpret_cast<const char*>(this)[sizeof(*this) - 1]
这要归功于C ++中的特殊豁免,它允许将对象重新解释为char数组。