केवल a
सुरक्षित रूप से सीधे नियुक्ति नई अभिव्यक्ति (जिसे हम संदर्भ में आसानी के लिए x
फोन करता हूँ) द्वारा बनाई गई Foo
वस्तु का उपयोग करने के लिए इस्तेमाल किया जा सकता है। b
का उपयोग std::launder
की आवश्यकता है।
a
का मूल्य [expr.new]/1 में निर्दिष्ट किया जाता: इकाई एक गैर सरणी वस्तु, नई अभिव्यक्ति का परिणाम है
तो निर्मित ऑब्जेक्ट के लिए सूचक है।
a
का मान इसलिए "x
पर सूचक" है। यह पॉइंटर, निश्चित रूप से x
तक पहुंचने के लिए सुरक्षित रूप से उपयोग किया जा सकता है।
reinterpret_cast<Foo*>(buffer)
buffer
पर सरणी-से-पॉइंटर रूपांतरण लागू करता है ([expr.reinterpret.cast]/1 देखें)। रूपांतरण के बाद परिणामी मूल्य लागू होता है "buffer
के पहले तत्व के सूचक"। यह एक ऑब्जेक्ट पॉइंटर का एक reinterpret_cast
है जो किसी ऑब्जेक्ट पॉइंटर को किसी भिन्न प्रकार के ऑब्जेक्ट पॉइंटर पर है, और static_cast<Foo*>(static_cast<void*>(buffer))
के बराबर [expr.reinterpret.cast]/7 के रूप में परिभाषित किया गया है।
आंतरिक कास्ट void*
वास्तव में एक निहित रूपांतरण है। प्रति [conv.ptr]/2,
पॉइंटर मान इस रूपांतरण से अपरिवर्तित है।
इसलिए भीतरी डाली मूल्य "buffer
के पहले तत्व के लिए सूचक" के साथ एक void*
अर्जित करता है।
प्रकार का एक prvalue "सूचक को CV1void
" प्रकार का एक prvalue में बदला जा सकता "सूचक:
बाहरी कलाकारों [expr.static.cast]/13, जो मैं हल्के से बुलेट बिंदुओं में पुन: स्वरूपित किया द्वारा नियंत्रित होता है CV2T
", जहाँ T
एक वस्तु प्रकार और CV2 है के रूप में एक ही सीवी-योग्यता, या अधिक से अधिक सीवी-योग्यता, CV1 है।
मूल सूचक मूल्य स्मृति में एक बाइट का पता A
का प्रतिनिधित्व करता है और A
T
के संरेखण आवश्यकता को पूरा नहीं करता है, फिर परिणामी सूचक मूल्य अनिर्दिष्ट है।
अन्यथा, यदि एक वस्तु a
, और वहाँ एक वस्तु प्रकार T
की b
है करने के लिए मूल सूचक मूल्य अंक (अनदेखी सीवी-योग्यता) कि सूचक-बदलने के योग्य a
साथ है, परिणाम b
के लिए सूचक है ।
अन्यथा, सूचक मूल्य रूपांतरण द्वारा अपरिवर्तित है।
यह मानते हुए कि buffer
उपयुक्त रूप से गठबंधन किया है (आप मुसीबत में अच्छी तरह से इस बिंदु से पहले अगर यह नहीं है हो जाएगा), पहले बुलेट लागू नहीं है। दूसरा बुलेट इसी तरह अपरिहार्य है क्योंकि यहां कोई pointer-interconvertiblity नहीं है। यह इस प्रकार है कि हमने तीसरी गोली मार दी - "सूचक मूल्य रूपांतरण द्वारा अपरिवर्तित है" और "buffer
के पहले तत्व के सूचक" बना हुआ है।
इस प्रकार, b
Foo
ऑब्जेक्ट x
पर इंगित नहीं करता है; यह buffer
के पहले char
तत्व के बजाय इंगित करता है, भले ही इसका प्रकार Foo*
है। इसलिए इसका उपयोग x
तक पहुंचने के लिए नहीं किया जा सकता है; ऐसा करने का प्रयास अपरिभाषित व्यवहार पैदा करता है (गैर-स्थैतिक डेटा सदस्य मामले के लिए, [expr.ref] से चूककर; गैर-स्थिर सदस्य फ़ंक्शन केस के लिए, [class.mfct.non-static]/2 द्वारा)।
b
से x
के लिए सूचक को ठीक करने के लिए, std::launder
इस्तेमाल किया जा सकता:
b = std::launder(b); // value of b is now "pointer to x"
// and can be used to access x
नई (बफर) फू; वस्तु के निर्माता को बुलाएगा; दूसरा नहीं है। – UKMonkey
@UKMonkey: क्षमा करें, शायद मैं पर्याप्त स्पष्ट नहीं था। दोनों लाइनें चलती हैं, पहले प्लेसमेंट नई, और फिर कास्ट। – geza
हां, कक्षा में कॉन्स सदस्य होने पर कोई अंतर होता है। विवरण के लिए [यह प्रश्न] देखें (https://stackoverflow.com/questions/47473621/placement-new-and-assignment-of-class-with-const-member)। – DaBler