2017-08-26 9 views
8

Facebook'un fbstring_core sınıf sınıfının veri üyeleri için depolama burada this talk anlatıldığı "Küçük dize Optimizasyonu" kullanır. Bu durumlar arasında ayrım yapmak için kullanılan bayrak bitleri, "depolamanın en sağdaki karakterinde" bulunur. Sorum şu ki, bu bitlere hiçbir zaman gerçekten yazılmamış olan bytes_ sendika üyesine ulaşıp ulaşamayacağınız, C++ 11 standardı başına tanımlanmamış bir davranış mı oluşturuyor? Accessing inactive union member and undefined behavior? cevabı, bunu önerdi.FBString'in küçük dize eniyilemesi tanımsız davranışa dayanıyor mu? Bir <code>Char*</code>, <code>size</code> ve <code>capacity</code> - - dize yeterince küçükse mağaza karakter verilerine başka bir amaca uygun olacaktır

Aşağıdaki alıntı, bu üyelerin bildirimini ve bu optimizasyonun etkin olup olmadığını belirlemek için kullanılan category() üye işlevini içerir.

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_; 
    }; 

uygulama aslında size_t capacity_ üyesinin parçası olabilecek bir bayt erişmek için "tip cinaslı" seçeneğini kullanarak dayanıyor gibi görünüyor. Yukarıda bağlantılı soruya verilen yanıttan, bu 'un C99'da tanımlanmış davranışı olduğunu, ancak C++ 11'de değil mi?

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

var:

+1

Herhangi bir imzanın "karakterine" erişim her zaman izin verilir. – o11c

+1

Boost'taki benzer bir kod, bir hatayla sonuçlandı: https://svn.boost.org/trac10/ticket/12183 –

+0

@ o11c: '' uint8_t' '' 'char'' türü için bir takma ad olarak tanımlandı mı? Yine de? 'İmzasız char'' kullanmak daha güvenli görünüyor. –

cevap

11

Sadece bu bytes_ tek kullanım UB olmadan yapılabilir this son byte, okumak için görünmektedir, çünkü oldukça gereksiz, UB gibi görünen C++ 'daki nesnelere tekrar tekrar izin veren özel diziler sayesinde.

İlgili konular