2008-11-14 12 views
9

सी ++ मानक निर्देश देता है कि एकल एक्सेस अनुभाग के अंदर सदस्य चर को उसी क्रम में स्मृति में रखा जाना चाहिए, उसी समय, संकलक स्वयं एक्सेस अनुभागों के पारस्परिक क्रम को चुनने के लिए स्वतंत्र हैं। यह स्वतंत्रता सिद्धांत में असंभव बनाता है कि विभिन्न कंपाइलरों द्वारा बनाई गई बाइनरी को लिंक करें। तो सख्त इन-सेक्शन ऑर्डरिंग के शेष कारण क्या हैं? और आगामी सी ++ 09 नया सी ++ 11 मानक ऑब्जेक्ट लेआउट को "हाथ से" निर्धारित करने का एक तरीका प्रदान करता है?सी ++ में कक्षा लेआउट: कभी-कभी सदस्यों को आदेश क्यों दिया जाता है?

+0

सी ++ 11 ने यह स्पष्ट करने के लिए संशोधित किया कि _repeated_ एक्सेस विनिर्देशकों को हस्तक्षेप करना (जो भी कारण हो सकता है उनमें से कोई भी लेआउट गारंटी में बाधा नहीं डालता है; यह तब होता है जब पहुंच स्तर _different_ विनिर्देशक के माध्यम से बदलता है, पिछले के दोहराव नहीं। –

उत्तर

8

यह स्वतंत्रता सिद्धांतों में विभिन्न कंपाइलरों द्वारा बनाई गई बाइनरी को लिंक करना असंभव बनाता है।

कई कारणों से असंभव है, और संरचना लेआउट सबसे मामूली है। vtables, operator new और delete, डेटा प्रकार आकार के कार्यान्वयन ...

तो क्या सख्त में अनुभाग आदेश देने के लिए शेष कारण हैं?

सी अनुकूलता, मैं सोचा होगा, ताकि एक struct सी में परिभाषित किसी दिए गए संकलक सेट के लिए उसी तरह यह C++ करता पैक।

और नई सी ++ 11 मानक एक तरह से पूरी तरह से वस्तु लेआउट निर्धारित करने के लिए "हाथ से" प्रदान करता है?

नहीं, वर्तमान मानक से अधिक नहीं।

class या struct के लिए कोई vtable और पूरी तरह से निजी (या सार्वजनिक) फ़ील्ड्स के साथ, हालांकि, यदि आप [u]int[8|16|32|64]_t प्रकारों का उपयोग करते हैं, तो यह पहले से ही संभव है। इस से अधिक के लिए आपके पास क्या उपयोग केस है?

+0

> इससे अधिक के लिए आपके पास क्या उपयोग केस है? अनुकूलन।ऑब्जेक्ट्स को अपने डेटा सदस्यों को फिर से ऑर्डर करके छोटा बनाया जा सकता है। कोड में क्रम अक्सर सदस्यों के तार्किक समूहों को दर्शाता है, इसलिए आप इसे बदलना नहीं चाहते हैं। –

0

संपादित करें: मुझे डर है कि मैं आपके सवाल का

गलत समझा मुझे लगता है कि स्मृति का उपयोग के लिए एक अनुकूलन हूँ। उदाहरण के लिए, अगर हम इस संरचना है:

struct example 
{ 
    int16 intData; 
    byte byteData; 
    int32 intData; 
    byte intData; 
    int32 intData; 
} 

के इस मंच में शब्द लगता है चलो 32 बिट कर रहे हैं। तो फिर तुम 4 पूर्ण शब्दों की आवश्यकता होगी struct में सभी डेटा पारित करने के लिए:

int16 + बाइट = 24 बिट (NetX क्षेत्र यहाँ फिट नहीं करता है)

int32 = 32 बिट (NetX क्षेत्र यहाँ फिट नहीं करता है)

बाइट = 8 बिट (NetX क्षेत्र यहाँ फिट नहीं करता है)

int32 = 32 बिट

लेकिन तुम क्षेत्र को पुनर्व्यवस्थित करता है, तो एस:

struct example 
{ 
    int16 intData; 
    byte byteData; 
    byte intData; 
    int32 intData; 
    int32 intData; 
} 

तो आप एक मेमोरी एक्सेस को सहेज सकते हैं।

2

[संपादित करें] मैंने आज कुछ नया सीखा! निम्न मानक बोली पाया:

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

दिलचस्प - मुझे नहीं पता कि इस डिग्री की आजादी क्यों दी जाती है। मेरे पिछले जबाब के बाकी th करने के लिए ...


जैसा कि बताया जा जारी रखते हुए, आदेश के संरक्षण के लिए कारण सी अनुकूलता है, और वापस तो मैं पुन: क्रम सदस्यों के लाभों में से कोई नहीं सोचा था कि लगता है, जबकि स्मृति लेआउट आम तौर पर किया गया था वैसे भी हाथ से। इसके अलावा, अब "बदसूरत चाल" माना जाएगा (जैसे मेमसेट के साथ चयनित सदस्यों को शून्य करना, या एक ही लेआउट के साथ दो structs होने) काफी आम थे।

मानक आपको दिए गए लेआउट को लागू करने का कोई तरीका नहीं देता है, लेकिन अधिकांश कंपाइलर पैडिंग को नियंत्रित करने के लिए उपाय प्रदान करते हैं, उदा। #pragma पैक एमएसवीसी कंपाइलर्स पर।

स्वचालित पैडिंग का कारण प्लेटफ़ॉर्म पोर्टेबिलिटी है: विभिन्न आर्किटेक्चर में अलग-अलग संरेखण आवश्यकताएं होती हैं, उदा। कुछ आर्किटेक्चर गलत गलतियों पर फेंक देते हैं (और फिर ये साधारण मामले थे)।

+0

नहीं, मुझे यकीन है कि वह सही है। मुझे इसे देखने के लिए यहां मानक तक पहुंच नहीं है, लेकिन मैंने पहले भी ऐसा देखा है। यह कहता है कि अलग-अलग पहुंच वर्गों के बीच आदेश अनिर्दिष्ट है, लेकिन एक खंड के भीतर, सदस्यों को घोषणा के आदेश में रखा गया है। मैंने भी सोचा कि बिंदु क्या था – jalf

+0

आप सही हैं, मैंने जवाब अपडेट किया है। अब मैं भी उत्सुक हूँ। – peterchen

+1

सी ++ 11 ने यह स्पष्ट करने के लिए संशोधित किया कि _repeated_ एक्सेस विनिर्देशकों को हस्तक्षेप करना (जो भी कारण हो सकता है उनमें से कोई भी लेआउट गारंटी को बाधित नहीं करता है; यह तब होता है जब पहुंच स्तर _different_ विनिर्देशक के माध्यम से बदलता है, पिछले के दोहराव नहीं। –

0

आपको कभी भी विभिन्न कंपाइलरों द्वारा बनाई गई वस्तुओं को लिंक नहीं करना चाहिए। यहां तक ​​कि यदि आप जो भी बात करते हैं, वह बदल जाता है, फिर भी आपके पास अभी भी अधिक समस्याएं हैं जो आपको किसी अन्य कंपाइलर की जेनरेट की गई फ़ाइलों के विरुद्ध लिंक करने से रोकती हैं। (संरेखित, नाम उलझन, सम्मेलन बुलावा केवल उनमें से कुछ नाम)।

एक कारण संकलक आसपास के एक्सेस अनुभागों को ऑर्डर करने के लिए स्वतंत्र है, इसलिए संकलक पहुंच अनुभागों के लिए एक ऑर्डर स्थापित कर सकता है: उदाहरण के लिए निम्न पते वाले सदस्यों की तुलना में निचले पते वाले सदस्य अधिक सुरक्षित हैं।

तुम कुछ भी हासिल नहीं होता है, तो यह है कि पुनर्व्यवस्था की अनुमति नहीं थी: केवल फली सी अनुकूलता और एक तरह से (मैक्रो offsetof का प्रयोग करके) देने के लिए आप एक वर्ग/struct अंदर सदस्यों की ऑफसेट बाइट या आप उन्हें memcpy की अनुमति देता है प्रदान करते हैं। यदि आप कस्टम कन्स्ट्रक्टर को परिभाषित करते हैं, तो कन्स्ट्रक्टर कॉपी करें, एक निजी सदस्य या कुछ अन्य सामान परिभाषित करें तो एक प्रकार गैर-पीओडी बन जाएगा। विशेष रूप से, एक वर्ग से प्राप्त करने से वर्तमान में पॉडनेस टूट जाता है।

सी ++ 1x पीओडी के लिए आवश्यकताओं को कम करता है। उदाहरण के लिए, सी ++ 1x std::pair<T, U> वास्तव में एक पीओडी है, भले ही यह अपना स्वयं का कन्स्ट्रक्टर प्रदान करता है (हालांकि कुछ नियमों को फिट करना है)।

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