2012-11-29 17 views
17

मैं एक सी ++ प्रोग्राम में निम्न कोड है कहते हैं:"नया (और चर) मान क्या है;" सी ++ में करते हैं?

Object a = Object(someParameters); 
new (&a) Object(someOtherParameters); 

मेरे इस धारणा है कि यह Object(someOtherParameters) साथ a की सामग्री को बदल, एक संभव operator=Object के लिए घोषित परहेज है। क्या ये सही है?

+2

मौजूदा उत्तरों के विपरीत के रूप में: आपके प्रश्न के * शीर्षक * में वाक्यविन्यास मौजूद नहीं है! आप किसी भी मूल्य के साथ इस वाक्यविन्यास का उपयोग नहीं कर सकते हैं, आप इसे केवल कन्स्ट्रक्टर कॉल में उपयोग कर सकते हैं - यानी 'मान'' टी (तर्क) 'फ़ॉर्म का होना चाहिए। –

+0

नियुक्ति नया हमेशा एक सी ++ मेमोरी पूल (ऑब्जेक्ट पूल) में उपयोग किया जाता है। अतिरिक्त उत्तर के रूप में। – Healer

उत्तर

21

इसे placement new कहा जाता है। यह नई स्मृति आवंटित करने के बजाय निर्दिष्ट स्मृति पर निर्माता को कॉल करता है। ध्यान दें कि आवंटित स्मृति को मुक्त करने से पहले आपको इस मामले में स्पष्ट रूप से अपने ऑब्जेक्ट के विनाशक को कॉल करना होगा।

स्पष्टीकरण। मान लीजिए कि आपने कुछ कच्ची मेमोरी

char * rawMemory = new char [sizeof (Object)]; 

आवंटित की है और आप उस स्मृति पर एक ऑब्जेक्ट बनाना चाहते हैं। आप

new(rawMemory) Object(params); 

अब फोन, स्मृति

delete [] rawMemory; 

आप अपने विशिष्ट उदाहरण में वस्तु को स्पष्ट रूप से

reinterpret_cast<Object*>(rawMemory)->~Object(); 

की derstuctor फोन करना होगा, हालांकि, संभावित समस्या है मुक्त कराने से पहले कि आपने अपनी स्मृति में एक नया निर्माण करने से पहले मौजूदा ऑब्जेक्ट को सही तरीके से नष्ट नहीं किया है।

बोनस: कभी सोचा कैसे मानक std::vector अपने निहित वस्तुओं डिफ़ॉल्ट-constructible किया जा रहा बिना कर सकता है? कारण यह है कि अधिकतर, यदि सभी नहीं, कार्यान्वयन allocator<T>T* p स्टोर नहीं करता है जिसके लिए p = new T[N] के मामले में टी को डिफ़ॉल्ट-रचनात्मक होने की आवश्यकता होगी। इसके बजाए यह char पॉइंटर - कच्ची मेमोरी संग्रहीत करता है, और p = new char[N*sizeof(T)] आवंटित करता है। जब आप push_back ऑब्जेक्ट करते हैं, तो यह उस चार सरणी में उपयुक्त पते पर प्रतिस्थापन के साथ कॉपी कन्स्ट्रक्टर को कॉल करता है।

+0

अंतिम वाक्य भ्रमित/गलत है: ऑब्जेक्ट की स्मृति मुक्त होने से पहले विनाशक को स्वचालित रूप से दायरे के अंत में बुलाया जाता है। लेकिन पहले से मौजूद * ऑब्जेक्ट के लिए विनाशक इसे ओवरराइट करने से पहले बुलाया जाना चाहिए। अतिरिक्त भलाई के लिए, इस उत्तर में ऑपरेटर को अधिभारित करने की संभावना का भी उल्लेख करना चाहिए - संभावित रूप से एक अधिभार कुछ पूरी तरह से अलग करता है। –

+2

@ कोनराड रुडॉल्फ: नहीं, यह नहीं है। 'कक्षा * ऑब्जेक्ट = नया (कच्चा मेमरी) कक्षा (पैरा); 'आप बाद में' ऑब्जेक्ट डिलीट 'नहीं कर सकते; क्योंकि स्मृति सामान्य' नई 'द्वारा आवंटित नहीं की गई थी। इसलिए, आपको 'delete [] rawMemory' को हटाने से पहले स्पष्ट रूप से' ऑब्जेक्ट-> ~ कक्षा() 'को कॉल करना होगा। –

+0

ओपी के प्रश्न में ऑब्जेक्ट स्टैक-आवंटित और सही प्रकार का है, इसलिए आपका आपत्ति लागू नहीं होती है।गतिशील रूप से आवंटित स्मृति के लिए भी, आप निम्न को बहुत अच्छी तरह से कर सकते हैं: 'टी * एक्स = नया टी; x-> ~ टी(); नया (एक्स) टी(); एक्स हटाएं; '(विनाशक कॉल और प्लेसमेंट नया आदेश दें!) –

6

इसे प्लेसमेंट नया के रूप में जाना जाता है: यह कोष्ठक के अंदर दिए गए पते पर नया Object बनाता है। प्लेसमेंट नया आमतौर पर कच्ची मेमोरी में ऑब्जेक्ट बनाने के लिए प्रयोग किया जाता है। मौजूदा कोड के शीर्ष पर एक नई वस्तु का निर्माण, जैसा कि यह कोड करता है, एक बुरा विचार है, क्योंकि यह मूल वस्तु पर विनाशक को नहीं बुलाता है।