在析构函数的最后一行,我有一个诊断类型的消息,它采用printf
形式:
"object destroyed at %p", this
我担心this
在这一点上的定义有多好。
我应该预约吗?行为定义明确吗?
答案 0 :(得分:7)
根据C ++标准(12.4 Destructors)
8 执行析构函数体后破坏任何析构函数 在体内分配的自动对象,类的析构函数 X调用X的直接非变量非静态数据的析构函数 成员,X的直接基类的析构函数,如果X是 最派生类的类型(12.6.2),它的析构函数调用 X的虚拟基类的析构函数。
所以你的代码格式正确。在执行析构函数体之后,将调用所有非静态数据成员和基类的析构函数。
答案 1 :(得分:2)
嗯,指针本身当然仍然存在(毕竟它只是一个地址)。打印指针值应该没有问题。
另一方面,你在析构函数中所做的一切都已经发生了。属性可能已经是delete
'等,所以你必须避免任何访问它们的东西。
答案 2 :(得分:1)
这有完全明确的行为。考虑在整个析构函数中隐式或显式地使用this
指针,例如每当您访问delete ptr_;
之类的成员变量时。 在析构函数返回 之后,成员将按照声明/创建的相反顺序销毁,然后调用基本析构函数。
答案 3 :(得分:0)
正如您现在所做的那样,您可以从析构函数中访问您的类成员。如果this
指针无效,这将无效。因此,您可以放心地假设地址this
指向的地址仍然与您在构造函数中打印的地址相同。
答案 4 :(得分:0)
在析构函数中,this
指针定义得很好,所有成员和基数(在析构函数返回后将以构造逆序中销毁)也是如此。所以打印它所引用的地址不是UB。
唯一的事情是对象本身不能再被假定为“多态”,因为派生的组件已被破坏。
class A
{
public:
virtual void fn() { std::cout << "A::fn" << std::endl; }
virtual ~A() { fn(); } //< will call A::fn(), even if B is destroying
};
class B: public A
{
public:
virtual void fn() { std::cout << "B::fn" << std::endl; }
virtual ~B() {}
};
int main()
{
B b;
A& a = b;
a.fn(); //< will print B::fn(), being A::fn virtual and being B the runtime-type of the a's referred object
return 0; //< will print A::fn() from b's A's component destructor
}