我需要销毁 new class 的每个实例吗?

Do I need to destroy each instance of new class?

本质上,如果我创建一个新的 class 的多个实例,我是否需要为每个实例调用析构函数,或者在每个实例销毁后调用它(如果我使用 [=,我深表歉意) 21=] 个术语,constructors/destructors 是我还没有完全掌握的概念)。

更具体地说,这是我正在使用的一些代码(如果风格不好,我将不得不再次道歉,我有一个学校问题的想法,想尽快把代码写下来) .

while(read >> f >> l >> t >> s >> sta >> acct >> bal)
{
    cout << "test" << endl;
    ptr[i] = new account(f,l,t,s,sta,acct,bal);
    ptr[i]->printcontents();
    cout << "test" << endl;
    i++;
    cout << i << endl;
}

所以为了这个问题,假设这将循环三次。我是否只需要调用一次 "account" 的析构函数来销毁新帐户的所有三个实例,或者一个调用会离开另外两个?这甚至是一个好习惯吗?

编辑:我注意到我的一些 post 被截断了,所以我添加了最后几行,但人们已经解决了这个问题。我是用户指针的原因纯粹是因为作业要求我这样做;坦率地说,我现在看不到使用它们的意义,但我认为它们会在某个地方变得有用。我还应该补充一点,动态内存分配也应该用于分配。

每个 new 应该用 delete

来平衡

如果您有一个指针数组,并且每个指针 new,则每个实例需要 delete

另一方面,如果您 new 对象数组,则可以 delete [] 整个数组。

附带一点,对于您的代码,而不是使用 ptr(您没有告诉我们详细信息,请考虑仅使用 std::vector<account> 并使用 push_back然后它将根据需要自动调整大小,而不是 ptr[i] = new....

析构函数会自动调用,您通常不必担心 除非您使用 new.

动态分配内存

在这种情况下,一旦您不再需要分配的每个内存,就必须调用 delete

请注意,如果您使用 new [] 分配数组,则必须使用 delete[] 进行取消分配:

int *a = new int[10]; // allocating an array of 10 integers

//...

delete[] a; // release memory

在现代 C++ 中,您应该考虑托管指针来完成这项工作。类似于:

while(read >> f >> l >> t >> s >> sta >> acct >> bal)
{
    cout << "test" << endl;
    ptr[i] = std::make_unique<account>(f,l,t,s,sta,acct,bal);
    ptr[i]->printcontents();
    cout << "test" << endl;
    i++;
    cout << i << endl;
}

在这里,std::make_unique 将 return 一个 std::unique_ptr 将在销毁时调用关联内存上的 delete。


最后一点:你确定你真的需要指点吗?从你的例子很难说,但根据你的使用情况,你也可以创建静态分配的对象:

while(read >> f >> l >> t >> s >> sta >> acct >> bal)
{
    cout << "test" << endl;
    ptr[i] = account(f,l,t,s,sta,acct,bal);
    ptr[i].printcontents();
    cout << "test" << endl;
    i++;
    cout << i << endl;
}

通常您必须删除您创建的每个实例。具体怎么做取决于一点……但简单的经验法则:

每次使用 new 都必须使用 delete

每次使用 new[] 都必须使用 delete[]

如果您从自动声明中获取实例,则无需执行任何操作,因为它将连同其堆栈框架一起销毁;但如果你创造了它,你就摧毁了它。

正如其他人所指出的,如果你使用new那么你将需要delete。但是,您真正的麻烦是概念上的。你问了一个很好的问题 newdelete 是外围的。

99.5% 以上的正常使用析构函数是为了让编译器自动调用它们。 (0.5% 的例外是深奥的。我们现在不需要担心这个。)

考虑这个代码片段:

  int n = 5;
  {
    int m = 2;
    ++m;
    n *= m;
    // The variable m is automatically destructed here.
  }
  // Here, n == 15.

看看效果如何? m 的析构函数在 m 到达其生命周期结束时自动调用,这(因为 m 不是用 new 创建的)发生在块的末尾m 被实例化。

当然,m 是一个 int,因此它的析构函数不执行任何操作(或者,如果您愿意,m 没有析构函数)。您自己定义的其他类型,例如您的类型 account,可以有析构函数。当单个对象(account 的一个实例)到达其生命周期的尽头时,针对单个对象自动 调用析构函数。

新建和删除

那么,这与newdelete有什么关系呢?

在我的代码片段中,我没有使用new。因此,我的对象的生命周期由大括号控制。

在您的代码片段中,您确实使用了 new。因此,对象的生命周期由 delete.

的使用控制

当然,你忘了使用 delete,所以这就是你的对象从未被破坏的原因(除非你的整个程序退出)。

其他人注意到现代 C++ 提供了改进的 new 替代方案,您应该在大多数情况下使用它们。您可以阅读他们的答案。然而,从机械上讲,理解普通 new 的作用以及 delete 如何与之配对仍然很有帮助。

手动调用析构函数

您几乎可以肯定不必担心这一点,因为手动调用析构函数的情况很少见且高级。基本上,如果您自己管理存储对象的内存(您几乎从不这样做,但也有极少数例外),那么编译器无法判断何时析构,因此您必须告诉它何时析构。有关典型的深奥示例,请参阅 this

只有指针需要调用析构函数来删除它们或关闭程序