मैंने इसमें ::delete
एक वर्ग के लिए कॉल करने की कोशिश की operator delete
। लेकिन विध्वंसक नहीं कहा जाता है।
मैंने एक ऐसे वर्ग को परिभाषित किया MyClass
जिसका operator delete
भार अधिक हो गया है। वैश्विक operator delete
भी अतिभारित है। अतिभारित operator delete
की MyClass
अतिभारित वैश्विक फोन करेगा operator delete
।
class MyClass
{
public:
MyClass() { printf("Constructing MyClass...\n"); }
virtual ~MyClass() { printf("Destroying MyClass...\n"); }
void* operator new(size_t size)
{
printf("Newing MyClass...\n");
void* p = ::new MyClass();
printf("End of newing MyClass...\n");
return p;
}
void operator delete(void* p)
{
printf("Deleting MyClass...\n");
::delete p; // Why is the destructor not called here?
printf("End of deleting MyClass...\n");
}
};
void* operator new(size_t size)
{
printf("Global newing...\n");
return malloc(size);
}
void operator delete(void* p)
{
printf("Global deleting...\n");
free(p);
}
int main(int argc, char** argv)
{
MyClass* myClass = new MyClass();
delete myClass;
return EXIT_SUCCESS;
}
आउटपुट है:
Newing MyClass...
Global newing...
Constructing MyClass...
End of newing MyClass...
Constructing MyClass...
Destroying MyClass...
Deleting MyClass...
Global deleting...
End of deleting MyClass...
वास्तविक:
ओवरलोड होने से पहले विध्वंसक को केवल एक कॉल करना operator delete
है MyClass
।
अपेक्षित होना:
विध्वंसक को दो कॉल हैं। अतिभारित कॉल करने से पहले एक operator delete
के MyClass
। ग्लोबल कॉल करने से पहले एक और operator delete
।
::delete p;
अपरिभाषित व्यवहार का कारण बनता है क्योंकि जिस प्रकार का *p
ऑब्जेक्ट हटाया जा रहा है उसी प्रकार का नहीं है (और न ही वर्चुअल डिस्ट्रक्टर के साथ बेस क्लास)
void*
जैसा कि ऑपरेंड भी स्पष्ट रूप से बीमार है। [expr.delete] / 1 : " ऑपरेंड ऑब्जेक्ट प्रकार या वर्ग प्रकार के लिए पॉइंटर का होगा। [...] इसका मतलब यह है कि ऑब्जेक्ट को किसी प्रकार के शून्य के पॉइंटर का उपयोग करके हटाया नहीं जा सकता क्योंकि शून्य कोई ऑब्जेक्ट प्रकार नहीं है। * @ @ मैंने अपने उत्तर में संशोधन किया है।
MyClass::operator new()
(कम से कम)size
बाइट्स में कच्ची मेमोरी आवंटित करनी चाहिए । यह पूरी तरह से एक उदाहरण का निर्माण करने का प्रयास नहीं करना चाहिएMyClass
। के निर्माण केMyClass
बाद निष्पादित किया जाता हैMyClass::operator new()
। फिर, डिस्ट्रक्टरdelete
कोmain()
कॉल करता है, और मेमोरी को रिलीज़ करता है (डिस्ट्रॉक्टर को फिर से कॉल किए बिना)।::delete p
अभिव्यक्ति वस्तु के प्रकार के बारे में कोई जानकारी नहीं हैp
के बाद से, पर अंकp
एक हैvoid *
, इसलिए नाशक आह्वान नहीं कर सकते।