2017-08-26 16 views
8

फेसबुक के fbstring_core वर्ग "छोटे स्ट्रिंग अनुकूलन" this talk में वर्णित है जिसमें वर्ग 'डेटा सदस्यों के लिए भंडारण का उपयोग करता है। इन मामलों के बीच अंतर करने के लिए उपयोग की जाने वाली ध्वज बिट्स "भंडारण के दाएं चार" में स्थित हैं। मेरा सवाल यह है कि bytes_ यूनियन सदस्य के माध्यम से इन बिट्स तक पहुंचने के लिए, जो वास्तव में कभी लिखा नहीं गया है, सी ++ 11 मानक के अनुसार अपरिभाषित व्यवहार का गठन करता है? Accessing inactive union member and undefined behavior? का उत्तर यह बताता है।क्या एफबीस्ट्रिंग का छोटा स्ट्रिंग ऑप्टिमाइज़ेशन अपरिभाषित व्यवहार पर भरोसा करता है? एक <code>Char*</code>, <code>size</code> और <code>capacity</code> - - दुकान चरित्र आंकड़ों के पुनः प्रयोजन किया जाएगा यदि स्ट्रिंग पर्याप्त छोटा है

निम्नलिखित अंश में इन सदस्यों की घोषणा और 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_ सदस्य का हिस्सा हो सकता तक पहुँचने के लिए "प्रकार punning" का उपयोग पर निर्भर करता है कि। ऊपर दिए गए प्रश्न के उत्तर से, मैं इकट्ठा करता हूं कि यह सी 99 में परिभाषित व्यवहार है, लेकिन सी ++ 11 में नहीं है?

+1

किसी भी हस्ताक्षर के 'चार' तक पहुंच हमेशा की अनुमति है। – o11c

+1

बूस्ट में कुछ समान कोड जिसके परिणामस्वरूप एक बग हुई: https://svn.boost.org/trac10/ticket/12183 –

+0

@ o11c: '' uint8_t'' '' char'' प्रकार के लिए उपनाम है , हालांकि? '' हस्ताक्षरित चार' 'का उपयोग करना सुरक्षित लगता है। –

उत्तर

11

इतना ही नहीं यूबी प्रतीत होता है, यह काफी अनावश्यक है, क्योंकि bytes_ का ही उपयोग this के अंतिम बाइट, जो यूबी बिना किया जा सकता पढ़ने के लिए प्रतीत होता है:

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

है कि सी ++ में विशेष छूट के लिए धन्यवाद जो वस्तुओं को चार सरणी के रूप में पुन: परिभाषित करने की अनुमति देता है।

संबंधित मुद्दे