我正在尝试显式调用对象的析构函数。以下代码按预期工作:
class Foo {
public:
~Foo() {
x_=x_+10;
std::cout << "x_ = " << x_ << std::endl;
}
int x() {
return x_;
}
int x_=0;
};
int main()
{
Foo f;
std::cout << "f.x() = " << f.x() << std::endl;
f.~Foo();
f.~Foo();
std::cout << "f.x() = " << f.x() << std::endl;
return 0;
}
打印输出为:
f.x() = 0
x_ = 10
x_ = 20
f.x() = 20
x_ = 30
正如预期的那样,每次调用析构函数时,x_都会增加10,因此我们看到从10扩展到20到30的过程。
但是,如果我们从析构函数中删除std::cout
,例如:
class Foo {
public:
~Foo() {
x_=x_+10;
}
int x() {
return x_;
}
int x_=0;
};
int main()
{
Foo f;
std::cout << "f.x() = " << f.x() << std::endl;
f.~Foo();
f.~Foo();
std::cout << "f.x() = " << f.x() << std::endl;
return 0;
}
然后打印输出变为:
f.x() = 0
f.x() = 0
析构函数中的增量不再起作用。有人可以解释为什么打印语句会影响析构函数的行为吗?
答案 0 :(得分:0)
f.~Foo();
f.~Foo();
不要。只是不要。这是不好的。很坏。绝对不要这样做,尤其是当您不了解析构函数是什么时。
编译器只是跳过代码,因为这是未知领域,在这种情况下它会做任何想做的事情。
答案 1 :(得分:0)
使用损坏的对象是未定义的行为。因此,在析构函数结束后,将无法观察到对析构函数中对象stste的任何更改。
当您将析构函数增加10 ina时,编译器可以轻松证明这是不可观察的,因此无需在运行时浪费时间。
随后打印时,它可以复制值,加10,然后打印副本。但是编译器改为将其递增并打印。
在C ++标准下,具有未定义行为的程序在未定义行为之前和之后的行为均不受限制。
答案 2 :(得分:0)
{
Foo f;
f.~Foo();
}
这是未定义的行为。 f
是具有自动存储持续时间的变量。这意味着它的生命周期是自动管理的,您不能明确地终止它的生命。
具有未定义行为的程序可以以任何方式运行,因此您不能依靠观察到的UB程序所做的任何事情。