ฉันพยายามโทร::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...
จริง:
มีเพียงหนึ่งเรียกร้องให้ destructor คือก่อนที่จะโทรมากเกินไปของoperator delete
MyClass
ที่คาดว่าจะ
มีการเรียกไปยัง destructor สองสาย หนึ่งก่อนที่จะโทรมากเกินไปของoperator delete
ก่อนที่จะเรียกอีกทั่วโลกMyClass
operator delete
::delete p;
ทำให้เกิดพฤติกรรมที่ไม่ได้กำหนดเนื่องจากประเภทของ*p
ไม่เหมือนกับชนิดของวัตถุที่ถูกลบ (หรือคลาสพื้นฐานที่มีตัวทำลายเสมือน)
void*
ตัวถูกดำเนินการแม้จะมีรูปแบบไม่ชัดเจน [expr.delete] / 1 : " ตัวถูกดำเนินการจะเป็นตัวชี้ไปยังชนิดของวัตถุหรือประเภทของคลาส [... ] นี่หมายความว่าวัตถุไม่สามารถลบได้โดยใช้ตัวชี้เป็นโมฆะประเภทเพราะเป็นโมฆะไม่ได้เป็นประเภทวัตถุ * "@OP ฉันได้แก้ไขคำตอบแล้ว
MyClass::operator new()
ควรจัดสรรหน่วยความจำดิบจำนวนsize
ไบต์(อย่างน้อย)MyClass
มันไม่ควรพยายามที่จะสมบูรณ์สร้างตัวอย่างของ ตัวสร้างของจะถูกดำเนินการหลังจากที่MyClass
MyClass::operator new()
จากนั้นdelete
นิพจน์ในการmain()
เรียก destructor และปล่อยหน่วยความจำ (โดยไม่เรียกตัว destructor อีกครั้ง)::delete p
แสดงออกมีข้อมูลเกี่ยวกับชนิดของวัตถุที่ไม่มีp
จุดเนื่องจากp
เป็นvoid *
จึงไม่สามารถเรียกใช้เตาเผา