【问题标题】:Destructor called for each object in an array为数组中的每个对象调用析构函数
【发布时间】:2011-11-21 02:03:18
【问题描述】:

我有一个对象数组:

Square sq[81];

我认为它使用默认构造函数来创建每个。

当我通过一个 for 循环来初始化每个对象时,它会为数组中的每个 Square 对象调用析构函数。

for (int k=0; k<9; k++) {
   for(int j=0; j<9; j++) {
      sq[count++] = Square(k, j);
   }
}

Square(k, j)被调用的时候,是不是删除了sq[]中的对象,然后新建了一个?

【问题讨论】:

  • 看看各种构造函数、析构函数和赋值运算符何时发生可能很有启发性:codepad.org/S1iH4cWD
  • @Bill:非常好,除了在op= 期间复制 dtor 计数时会令人困惑。重点是识别对象,而不是内容 :) 所以,codepad.org/ofmZpriv 可能更有意义。
  • @Tomalak:谢谢!我使用 dtor 计数来证明数组中的对象已被覆盖。更完整的示例可以分别跟踪初始值和分配值。我将把它作为练习留给读者。 :)
  • @Tomalak:好吧,你说服了我。 ^^codepad.org/JPE8uYVO
  • @Bill:现在这只是令人困惑!

标签: c++ arrays destructor


【解决方案1】:

sq[] 的元素不会被破坏。相反,您调用每个元素的 赋值运算符 为其分配新值 Square(k, j),而临时对象在赋值结束时被销毁。

如果你想避免多余的默认构造加上赋值,你可以/应该使用向量:

std::vector<Square> sq;
sq.reserve(81);
for (...) for (...) sq.push_back(Square(k,j));

如果您进一步想避免多余的临时,请使用 C++11 并说,

for (...) for (...) sq.emplace_back(k, j);

【讨论】:

  • 但是当我在 for 循环期间为数组的每个元素调用我的析构函数时,我感到很困惑。
  • @DFord:对不起,我原来错了。正如 Tomalak 所说,您分配的 temporary 确实会被销毁;它的生命周期只跨越它发生的单行。在 C++11 中,您可以完全避免使用临时变量。
  • @Kerrek:谢谢你的回复,我明白它现在在做什么。
【解决方案2】:
sq[count++] = Square(k, j);

调用Square(k, j)的时候,是不是删除了sq[]里面的对象,再新建一个?

没有。

Square(k, j) 创建一个新的 temporary 对象,= 将其复制到旧对象中。临时对象随后被销毁,因为它不再需要并超出范围。


顺便说一句,你实际上并没有在循环中初始化任何东西(除了那个临时的,我的意思是);你只是在事后分配。

【讨论】:

  • 谢谢,我明白它现在在做什么了。
  • @Benjamin:是的,但不在循环中。我指的是“当我通过一个 for 循环来初始化每个”这句话。
【解决方案3】:

我们来看下面的示例程序:http://codepad.org/S1iH4cWD

你可以看到几个重要的步骤:

  • main 之前,Square sq[81] 中的每个对象都是默认构造的。
  • 在您的循环中,构造了一个临时对象,其内容被分配给 sq 中的一个对象 - 这会覆盖那里的对象 - 然后临时对象被销毁。
  • 最后,在main 之后,Square sq[81] 中的每个对象都被破坏,按照构造的相反顺序。

所以你几乎是对的,除了 sq 中的对象只会在 main 结束后被删除。被破坏的是临时的(=右侧的对象)。

您可能会发现此程序很有帮助:http://codepad.org/JPE8uYVO 它跟踪初始化和赋值的不同值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-29
    • 2010-10-16
    • 2015-05-02
    • 2019-09-30
    • 1970-01-01
    • 2010-11-10
    相关资源
    最近更新 更多