exp*_*inc 16 c++ delete-operator
我试图在其中召唤::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;
}
Run Code Online (Sandbox Code Playgroud)
输出为:
Newing MyClass...
Global newing...
Constructing MyClass...
End of newing MyClass...
Constructing MyClass...
Destroying MyClass...
Deleting MyClass...
Global deleting...
End of deleting MyClass...
Run Code Online (Sandbox Code Playgroud)
实际:
只有一个调用重载之前调用析构函数operator delete的MyClass。
预期:
有两个对析构函数的调用。调用重载之前的operator delete一个MyClass。另一个才叫全球operator delete。
wal*_*nut 17
您正在滥用operator new和operator delete。这些运算符是分配和释放函数。他们不负责构造或破坏对象。它们仅负责提供用于放置对象的内存。
这些函数的全局版本是::operator new和::operator delete。
::new和::delete是新的/删除表达式,因为是new/ delete从那些不同的,在那::new和::delete将绕过类特定operator new/ operator delete过载。
new / delete-expressions构造/销毁和分配/解除分配(通过调用适当的命令operator new或operator delete在构造之前或在销毁之后)。
由于您的重载仅负责分配/取消分配部分,因此应调用::operator new和::operator delete而不是::new和::delete。
在delete中delete myClass;负责调用析构函数。
::delete p;不调用析构函数,因为它p具有类型void*,因此表达式无法知道要调用的析构函数。::operator delete尽管将a void*操作数用作delete-expression的格式不正确,但它可能会调用您的replaced 来分配内存。
::new MyClass();调用您替换::operator new的对象来分配内存并在其中构造一个对象。返回该对象的指针,指向中void*的new-expression MyClass* myClass = new MyClass();,它将在该内存中构造另一个对象,从而在不调用其析构函数的情况下结束前一个对象的生存期。
编辑:
感谢@MM对这个问题的评论,我意识到void*as的操作数::delete实际上是格式错误的。([expr.delete] / 1)但是,主要的编译器似乎已决定仅对此警告,而不是错误。它是由前形成不良的,使用::delete上void*就已经不确定的行为,看到了这个问题。
因此,您的程序格式错误,如果仍然可以编译,则不能保证该代码确实执行了我上面描述的操作。
正如@SanderDeDycker在其答案下方所指出的那样,您还具有未定义的行为,因为通过在内存中构造一个已经包含MyClass对象的对象而不先调用该对象的析构函数,您就违反了[basic.life] / 5,如果程序取决于析构函数的副作用。在这种情况下,printf析构函数中的语句具有这种副作用。
San*_*ker 14
您特定于类的重载操作不正确。在输出中可以看到:构造函数被调用两次!
在特定于类的中operator new,直接调用全局运算符:
return ::operator new(size);
Run Code Online (Sandbox Code Playgroud)
同样,在特定于类的中operator delete,执行以下操作:
::operator delete(p);
Run Code Online (Sandbox Code Playgroud)
operator new有关更多详细信息,请参见参考页。
| 归档时间: |
|
| 查看次数: |
1253 次 |
| 最近记录: |