2013-01-16 25 views
5

संभव डुप्लिकेट:वर्ग चर - संरेखण

template<class T> 
class Vec3 { 
public: 
    // values 
    T x,y,z; 

    // returns i-th komponent (i=0,1,2) (RHS array operator) 
    const T operator[] (unsigned int i) const { 
    return *(&x+i); 
    } 
} 

या दूसरे शब्दों में: ऐसा क्यों है
Classes store data members in sequential memory?

बस पूछने के लिए क्यों निम्नलिखित सही है चाहता था हमेशा गारंटी है कि एक्स, वाई और जेड हमेशा स्मृति (टी) इकाइयों स्मृति में अलग हैं। क्या उन दो varibles के बीच कभी विखंडन छेद नहीं हो सकता है, इस प्रकार इस ऑपरेटर को झूठा मूल्य वापस करने दे?

+0

आप अनुक्रमण की जरूरत है, क्यों नहीं यह 'टेम्पलेट वर्ग Vector3 {सार्वजनिक: std :: सरणी XS; }; '? – Fanael

उत्तर

6

यह नहीं गारंटी है कि x, y और z हमेशा स्मृति में अलग हैं sizeof(T) इकाइयों। बीच में जोड़े गए पैडिंग बाइट्स हो सकते हैं।
इसे कार्यान्वयन के विवरण के रूप में छोड़ दिया गया है।
केवल गारंटी की बात यह है कि कक्षा/संरचना की शुरुआत और पीओडी संरचनाओं/कक्षाओं के लिए इसके पहले सदस्य के बीच कोई पैडिंग नहीं होगी।

यह गारंटी नहीं है कि आपके कोड में operator[] का कार्यान्वयन हमेशा काम करेगा।

संदर्भ:
सी ++ 11: 9.2 क्लास सदस्यों [class.mem]

14) Nonstatic डेटा एक (गैर संघ के) वर्ग में एक ही अभिगम नियंत्रण के साथ सदस्यों (खण्ड 11) आवंटित किए गए हैं कि बाद के सदस्यों के पास कक्षा वस्तु के भीतर उच्च पते हैं। गैर-स्थैतिक डेटा के विभिन्न अभिगम नियंत्रण वाले सदस्यों को आवंटित करने का आदेश निर्दिष्ट नहीं है (11)। कार्यान्वयन संरेखण आवश्यकताओं हो सकता है क्योंकि दो आसन्न सदस्यों को एक दूसरे के तुरंत बाद आवंटित नहीं किया जाना चाहिए; वर्चुअल फ़ंक्शंस (10.3) और वर्चुअल बेस क्लासेस (10.1) के प्रबंधन के लिए स्थान के लिए आवश्यकता हो सकती है।

+0

"इसका कार्यान्वयन विस्तार के रूप में छोड़ा गया है" का क्या मतलब है? –

+0

यहां तक ​​कि पहले सदस्य के पते से संबंधित गारंटी केवल पीओडी structs के लिए मान्य है।(या शायद सी ++ 11 में लेआउट संगत structs के लिए।) –

+0

@AdamMagaluk: इसका मतलब है कि संकलक वर्ग/संरचना सदस्यों के बीच आवश्यक पैडिंग के कई बाइट जोड़ने के लिए स्वतंत्र है। मानक इस संबंध में किसी भी विशिष्ट आवश्यकता को जरूरी नहीं है। –

0

आदेश विखंडन छेद आप संरेखण इस तरह से नियंत्रित कर सकते हैं से बचने के लिए:

#ifdef compiling_with_msvc 
#pragma pack(1) 
#endif 
template<class T> 
class Vec3 { 
public: 
    // values 
    T x,y,z; 

    // returns i-th komponent (i=0,1,2) (RHS array operator) 
    const T operator[] (unsigned int i) const { 
     return *(&x+i); 
    } 
#ifdef compiling_with_gcc 
}__attribute__((packed)); 
#else 
}; 
#endif 

आप एक C++11 compiler उपयोग कर सकते हैं, तो आप एक standard way में संरेखण नियंत्रित कर सकते हैं।

लेकिन अगर आप वर्ग की स्मृति प्रतिनिधित्व के बारे में परवाह नहीं है, के बारे में एक union उपयोग करने के लिए लगता है: संघ के साथ

template <typename T> 
union Vec3 
{ 
    T x, y, z; 
    struct 
    { 
     T value[3]; 
    } vector; 
}; 

, आप करने के लिए संरेखण के बारे में परवाह करने की जरूरत नहीं acces [] साथ प्रत्येक घटक:

Vec3<unsigned int> v3; 

v3.vector.value[0] = 1; 
v3.vector.value[1] = 2; 
v3.vector.value[2] = 3; 
+0

क्या यह वास्तव में कहीं निर्दिष्ट है कि, आपके संघ-समाधान में, फ़ील्ड गठबंधन किए जाएंगे (उदा। एक्स और मान [0], वाई और मान [1])? यह * भावना * बनाता है, लेकिन क्या यह वास्तव में कहीं भी निर्दिष्ट/गारंटीकृत है? – rmhartog

+0

हां, 'x' और' मान [0] ',' y' और 'मान [1]' ... का एक ही पता होगा ... लेकिन मैं गारंटी नहीं दे सकता कि 'x' <->' y', '' मान [0] '<->' मूल्य [1] 'आपको पैडिंग बाइट मिलेगा; यह 'यूनियन' के डेटा प्रकार, डेटा संरेखण और संरेखण नियंत्रण पर निर्भर करेगा –