我是否需要销毁新类的每个实例?

时间:2016-12-15 15:09:36

标签: c++ pointers constructor destructor

基本上,如果我创建一个新类的多个实例,我是否需要为每个实例调用析构函数,或者在销毁每个实例时调用它(如果我使用模糊/错误的术语,构造函数,我道歉/析构函数是我还没有完全掌握的概念。

更具体地说,这是我正在使用的一些代码(如果风格不好,我必须再次道歉,我对学校问题有了一个想法,并希望得到代码快)。

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;
}

因此,为了这个问题,假设这个循环三次。我是否只需要调用&#34; account&#34;的析构函数曾经摧毁所有三个新账户的情况,还是一个电话会离开另外两个?这甚至是一个好习惯吗?

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

5 个答案:

答案 0 :(得分:5)

自动调用析构函数,您通常不必担心,除非您使用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将返回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;
}

答案 1 :(得分:3)

每个new应该与delete

平衡

如果你有一个指针数组,并且每个指针都有new,那么你需要delete每个实例。

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

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

答案 2 :(得分:1)

通常,您必须删除您创建的每个实例。具体如何做到这一点取决于......但简单的经验法则是:

对于let youtubeURL = "https://www.youtube.com/watch?v=uH8o-JTHJdM" let regex = try! NSRegularExpression(pattern: "\\?.*v=([^&]+)", options: .caseInsensitive) let match = regex.firstMatch(in: youtubeURL, options: [], range: NSRange(location: 0, length: youtubeURL.characters.count)) if let videoIDRange = match?.rangeAt(1) { let substringForFirstMatch = (youtubeURL as NSString).substring(with: videoIDRange) } else { //NO video URL } 的每次使用,必须使用new

对于delete的每次使用,必须使用new[]

如果从自动声明中获取实例,则不必执行任何操作,因为它将使用其堆栈框架进行销毁;但如果你创造了它,就会将其销毁。

答案 3 :(得分:1)

正如其他人所说,如果你使用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被实例化。

当然,mint,因此它的析构函数不做任何事情(或者,如果您愿意,m没有析构函数)。您自己定义的其他类型(如类型account)可以包含析构函数。在单个对象(account的实例)达到其生命周期时,析构函数将自动针对单个对象进行调用。

新增和删除

那么,这与newdelete有何关系?

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

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

当然,您忘记使用delete,这就是为什么您的对象永远不会被破坏(除非您的整个程序退出)。

其他人已经注意到,现代C ++提供了new的改进替代方案,您应该在大多数情况下使用它。你可以阅读他们的答案。但是,从机械方面来说,理解new做什么以及delete如何配对它仍然非常有用。

手工调查导师

您几乎肯定不必担心这一点,因为手动调用析构函数的情况很少见且很先进。基本上,如果你自己管理一个存储对象的存储器(你几乎从不这样做,但很少有例外),那么编译器就无法分辨何时进行销毁,所以你必须在什么时候告诉它。有关典型的深奥示例,请参阅this

答案 4 :(得分:0)

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