Tôi đã cố gắng để gọi ::delete
cho một lớp học trong operator delete
đó. Nhưng kẻ hủy diệt không được gọi.
Tôi định nghĩa một lớp MyClass
mà operator delete
đã bị quá tải. Toàn cầu operator delete
cũng quá tải. Các quá tải operator delete
của MyClass
sẽ gọi toàn cầu quá tải 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;
}
Đầu ra là:
Newing MyClass...
Global newing...
Constructing MyClass...
End of newing MyClass...
Constructing MyClass...
Destroying MyClass...
Deleting MyClass...
Global deleting...
End of deleting MyClass...
Thực tế:
Chỉ có một cuộc gọi đến destructor trước khi gọi quá tải operator delete
của MyClass
.
Hy vọng:
Có hai cuộc gọi đến hàm hủy. Một trước khi gọi quá tải operator delete
của MyClass
. Khác trước khi gọi toàn cầu operator delete
.
::delete p;
gây ra hành vi không xác định do loại *p
không giống với loại đối tượng bị xóa (cũng không phải là lớp cơ sở với hàm hủy ảo)
void*
toán hạng thậm chí còn không rõ ràng. [expr.delete] / 1 : " Toán hạng sẽ là con trỏ tới loại đối tượng hoặc loại lớp. [...] Điều này ngụ ý rằng một đối tượng không thể bị xóa bằng cách sử dụng một con trỏ có kiểu void vì void không phải là một loại đối tượng. * "@OP Tôi đã sửa đổi câu trả lời của mình.
MyClass::operator new()
nên phân bổ bộ nhớ thô, của (ít nhất)size
byte. Nó không nên cố gắng xây dựng hoàn toàn một thể hiện củaMyClass
. Các constructor củaMyClass
được thực hiện sauMyClass::operator new()
. Sau đó,delete
biểu thức trongmain()
gọi hàm hủy và giải phóng bộ nhớ (không gọi lại hàm hủy). Các::delete p
biểu hiện không có thông tin về loại đối tượngp
điểm vào, vìp
là mộtvoid *
, vì vậy không thể gọi destructor.