classe Facebook fbstring_core utilise la « Petite chaîne d'optimisation » décrite dans this talk dans laquelle le stockage pour les données membres de la classe - un Char*
, size
et capacity
- sera réaffecté aux données de caractères magasin si la chaîne est suffisamment faible. Les bits de drapeau utilisés pour distinguer ces cas sont situés dans le "caractère le plus à droite du stockage". Ma question est de savoir si l'accès à ces bits par l'intermédiaire du membre syndical bytes_
, qui n'est jamais réellement écrit, constitue un comportement indéfini selon la norme C++ 11? La réponse à Accessing inactive union member and undefined behavior? suggère que c'est.L'optimisation de petite chaîne de FBString repose-t-elle sur un comportement indéfini?
L'extrait suivant contient la déclaration de ces membres et la fonction membre category()
utilisée pour déterminer si cette optimisation est effective.
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_;
};
Il semble que cette mise en œuvre repose sur l'utilisation de « type calembour » pour accéder à un octet qui pourrait en fait faire partie de l'organe size_t capacity_
. De la réponse à la question liée ci-dessus, je comprends que ce est comportement défini dans C99, mais pas en C++ 11?
L'accès à un «char» de toute forme est toujours autorisé. – o11c
Un code similaire dans Boost qui a entraîné un bogue: https://svn.boost.org/trac10/ticket/12183 –
@ o11c: Est-ce que '' uint8_t'' est défini comme étant un alias pour un type '' char'' , bien que? Il semble plus sûr d'utiliser '' unsigned char''. –