即使在明确调用破坏者后,对象自动破坏也是如此
Automatic destruction of object even after calling destructor explicitly
以下程序:
#include <iostream>
using namespace std;
class Test
{
public:
Test() { cout << "Constructor is executedn"; }
~Test() { cout << "Destructor is executedn"; }
};
int main()
{
Test(); // Explicit call to constructor
Test t; // local object
t.~Test(); // Explicit call to destructor
return 0;
}
打印以下输出:
Constructor is executed
Destructor is executed
Constructor is executed
Destructor is executed
Destructor is executed
我的问题即使是在Main()中明确调用destuructor之后,为什么编译器在退出Main()?
作为附带问题,除了在删除操作员中使用外,是否还有其他对策略明确调用destructor的使用?
您已经引入了未定义的行为。
根据标准:
§12.4Destructors
(11)驱动器被隐式调用
(11.3) - 对于具有自动存储持续时间(3.7.3)的构造对象,当对象为块时创建的出口(6.7),
和
15一旦调用了一个对象的驱动器,对象就不再存在;如果行为是不确定的,如果为一个生命结束的对象调用驱动器(3.8)。[示例:如果是自动对象被明确调用,然后以通常的方式保留该块援引对象的隐式破坏,行为是不确定的。 - 末尾示例]
您会明确调用击振子或调用t.~Test()
,然后在对象离开范围时隐式调用。这是不确定的。
标准也提供了此注释:
14 [注意:毁灭者的明确调用很少需要。此类呼叫的一种用途是用于放置在特定的对象使用安置新表达的地址。这种明确的放置和对象的破坏可以应付专用硬件资源并编写内存管理设施所需。
这不是"对构造函数的明确调用":
Test(); // Explicit call to constructor
它构造了一个临时对象,该对象隐含地称为构造函数,然后临时立即脱离范围,该范围隐含地称为破坏者。您无法明确调用构造函数,当您构造对象时,它被隐式称为。
我的问题即使是在Main()中明确调用destuructor之后,为什么编译器在退出Main()?
因为编译器总是会破坏本地变量。仅仅因为您做了一些愚蠢的事情(手动摧毁被自动销毁的物体)不会改变。
作为附带问题,除了在删除操作员中使用外,是否还有其他对策略明确调用destructor的策略?
在原始内存中管理对象的寿命时,它是由std::vector
和其他实用程序等容器完成的,例如std::optional
。
我的问题即使是在Main()中明确调用destuructor之后,为什么编译器在退出Main()?
当对象脱离范围时,无论您是否明确称呼攻击效果,攻击效果都将被调用。不要明确调用具有自动存储持续时间的对象的驱动器。
作为附带问题,除了在删除操作员中使用外,是否还有其他对策略明确调用destructor的策略?
是。当您使用位置new
表达式初始化对象时,您需要明确调用destructor。从上面网站中的示例代码:
char* ptr = new char[sizeof(T)]; // allocate memory
T* tptr = new(ptr) T; // construct in allocated storage ("place")
tptr->~T(); // destruct
delete[] ptr; // deallocate memory
t的范围是主要函数。它在堆栈上创建,并将在功能末尾被破坏。
这是应该的工作方式,当您尽早致电灾难时,您就不会更改。
您不需要致电驱动器,在这种情况下这样做会导致两次称为。
如果您使用过
Test* t = new Test();
在主的末尾不会自动调用破坏者。
编译器不在乎您是否明确调用destructor。局部对象t
脱离范围,这就是为什么它被破坏并称为击ol。明确称灾区是不是很好的做法。取而代之的是,您应该编写一个cleanup()
之类的方法,该方法可以明确地称为destructor中。如果您想避免使用该清理两次,请在您的课堂上添加类似的东西:
private:
bool cleanupPerformed;
void cleanup()
{
if( !cleanupPerformed )
{
// ... do cleanup work here ...
cleanupPerformed = true;
}
}
- 对RValue对象调用的LValue ref限定成员函数
- 检查哪个对象调用了另一个对象的对象方法
- 在 C++ 的 Switch Case 中创建对象后对对象调用方法
- 从 Base 引用对象调用派生类的成员
- 为什么为未删除的对象调用析构函数?
- Qt c++不会为所有对象调用move_slot.为什么?
- 使用在堆栈上创建的对象调用虚拟函数
- 使用基类对象调用Dervied Class函数
- C++:允许临时对象调用非常量成员函数的设计理念是什么?
- 从类中的对象调用类中的函数的最佳方法
- 派生对象调用的 Base 方法的模板推导
- 如何使用单个对象调用具有相同名称的两个类函数
- 是否可以从另一个类对象调用一个类函数而不继承第一个类
- 如果类没有任何成员变量,则通过临时对象调用类的成员函数的开销是多少?
- 如何对动态数组中的某些对象调用析构函数
- 如何从列表中存储的对象调用成员函数
- 从线程内的对象调用静态方法
- 从成员对象调用方法
- 当包含它的对象调用其析构函数时,unique_ptr是否未分配
- 从对象调用成员对象,错误:引用非常量值的初始值必须是左值