C++ C++;析构函数真的删除了东西吗?

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) {

我知道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)
{
  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()时,会发生什么情况

在您的示例中,没有任何内容,因为您没有删除该对象,而是

这样做有用吗

是的,是析构函数,这是调用析构函数的唯一情况。

这不是意外