8
Facebook的fbstring_core類使用this talk描述的「小字符串優化」,其中對於該類的數據成員存儲 - 一個Char*
,size
和capacity
- 將被重新用於存儲字符數據,如果該字符串是足夠小。用於區分這些情況的標誌位位於「存儲器的最右側字符」中。我的問題是,通過bytes_
聯合成員訪問這些比特是否構成未定義的行爲? Accessing inactive union member and undefined behavior?的答案表明它是。FBString的小字符串優化是否依賴未定義的行爲?
以下摘錄包含這些成員的聲明和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_;
};
看來,這實現依賴於使用「雙關式」訪問實際上可能是size_t capacity_
成員的一部分,一個字節。從上面鏈接的問題的答案中,我收集到這是在C99中定義的行爲,但而不是在C++ 11?
總是允許訪問任何簽名的「char」。 – o11c
Boost中導致bug的一些類似代碼:https://svn.boost.org/trac10/ticket/12183 –
@ o11c:是否將uint8_t定義爲char類型的別名,但?使用''unsigned char''似乎更安全。 –