C++ C++;析构函数真的删除了东西吗?
我知道delete操作符以及它如何自动调用类的析构函数。然而,我最近看到有人直接调用类的析构函数,这对我来说很奇怪。所以我写了一个简短的程序,给出了一个出乎意料的结果:C++ C++;析构函数真的删除了东西吗?,c++,C++,我知道delete操作符以及它如何自动调用类的析构函数。然而,我最近看到有人直接调用类的析构函数,这对我来说很奇怪。所以我写了一个简短的程序,给出了一个出乎意料的结果: #include <stdio.h> class A { public: A() {a = new int; *a=42; b=33;} ~A() {delete a;} int* a; int b; }; int main(int argc, const char ** argv) {
#include <stdio.h>
class A
{
public:
A() {a = new int; *a=42; b=33;}
~A() {delete a;}
int* a;
int b;
};
int main(int argc, const char ** argv)
{
A* myA = new A();
printf("a:%d b:%d\n", *(myA->a), myA->b);
myA->~A();
printf("b:%d\n", myA->b);
printf("a:%d\n", *(myA->a));
}
。。。为什么?当我直接调用~A()时,会发生什么情况?有没有这样做有用的情况?手动调用析构函数就像调用函数一样-代码被执行,但内存没有被释放,而不是在内存被释放时调用
delete
删除后访问
a
将导致未定义的行为,并且可能会出现工作状态。手动调用析构函数就像调用函数一样-代码会被执行,但内存不会被释放,而不是在内存被释放时调用delete
在删除后访问a
将导致未定义的行为,并且可能看起来有效
正如您所看到的,我正在调用析构函数~A(),因此我的预期是,当第二次尝试访问变量“A”时,程序会崩溃(因为它在两行之前被删除)。相反程序仅打印此文件,没有任何投诉:
a:42 b:33
b:33
a:42
不足为奇。正如您所注意到的,代码有缺陷。所以它不会做你期望的事情,而是一些难以预测或理解的事情。如果希望代码的行为可以预测,那么必须遵循规则。这就是他们的目的
“有人告诉我,在篮球运动中,你不能持球跑动。我买了一个篮球,试了试,效果很好。他显然不懂篮球。”——罗杰·米勒
正如您所看到的,我正在调用析构函数~A(),因此我的预期是,当第二次尝试访问变量“A”时,程序会崩溃(因为它在两行之前被删除)。相反程序仅打印此文件,没有任何投诉:
a:42 b:33
b:33
a:42
不足为奇。正如您所注意到的,代码有缺陷。所以它不会做你期望的事情,而是一些难以预测或理解的事情。如果希望代码的行为可以预测,那么必须遵循规则。这就是他们的目的
“有人告诉我,在篮球运动中,你不能持球跑动。我买了一个篮球,试了试,效果很好。他显然不懂篮球。”——罗杰·米勒
直接调用~A()时,将执行析构函数的代码。这不会阻止析构函数通常被C++调用。例如:
void func()
{
A a;
a.~A(); // calls destructor
// Destructor runs again here as it always would.
}
在您的示例中,int的内存将被释放。这只是意味着运行时会记录下你的程序不再使用内存。。。但这并不一定意味着记忆会立即被抹去或用于其他用途。因此,当您稍后访问int的内存时,它仍然包含相同的值。但是,其他线程可能会重用该内存,而其他线程可能会覆盖该内存,但您的程序中不会发生这种情况
直接调用~A()非常有用的一种情况是,您需要为某些需要优化的情况处理自己的内存分配。例如,您可以拥有自己的字符串类并一次性保留大量内存。您可以手动调用构造函数和析构函数,将此池中的内存区域设置为正确初始化的字符串。您可以这样做,而无需进行任何新的分配—只需重用池即可。但是我想说,这是专家级编程,您需要知道自己在做什么,并且这样做是为了获得有价值的性能提升。当您直接调用~a()时,将执行析构函数的代码。这不会阻止析构函数通常被C++调用。例如:
void func()
{
A a;
a.~A(); // calls destructor
// Destructor runs again here as it always would.
}
在您的示例中,int的内存将被释放。这只是意味着运行时会记录下你的程序不再使用内存。。。但这并不一定意味着记忆会立即被抹去或用于其他用途。因此,当您稍后访问int的内存时,它仍然包含相同的值。但是,其他线程可能会重用该内存,而其他线程可能会覆盖该内存,但您的程序中不会发生这种情况
直接调用~A()非常有用的一种情况是,您需要为某些需要优化的情况处理自己的内存分配。例如,您可以拥有自己的字符串类并一次性保留大量内存。您可以手动调用构造函数和析构函数,将此池中的内存区域设置为正确初始化的字符串。您可以这样做,而无需进行任何新的分配—只需重用池即可。但是我想说这是专家级编程,您需要知道自己在做什么,并且为了获得有价值的性能增益而这样做
当第二次尝试访问变量“a”时,程序应崩溃
访问已删除的变量是一种未定义的行为。这意味着任何事情都可能发生,包括程序崩溃
当我直接调用~A()时,会发生什么情况
在您的示例中,没有任何内容,因为您没有删除该对象,而是
这样做有用吗
是的,析构函数,这是调用析构函数的唯一情况
当第二次尝试访问变量“a”时,程序应崩溃
访问已删除的变量是一种未定义的行为。这意味着任何事情都可能发生,包括程序崩溃
当我直接调用~A()时,会发生什么情况
在您的示例中,没有任何内容,因为您没有删除该对象,而是
这样做有用吗
是的,是析构函数,这是调用析构函数的唯一情况。这不是意外