循环内局部对象的析构函数是否保证在下一次迭代之前被调用?

use*_*931 13 c++ destructor

当我有一个循环并且在这个循环内创建一个新的堆栈变量(不将它分配在堆上并在循环体内声明它的变量),是否保证在下一次迭代开始之前调用这个对象的析构函数,或者可能编译器展开的循环会改变什么?

Pau*_*ans 9

来自n4800

§6.3.3块范围

在块 (8.3) 中声明的名称是该块的本地名称;它有块作用域。它的潜在作用域从它的声明点 (6.3.2) 开始,并在其块的末尾结束。在块范围内声明的变量是局部变量。

§10.3.6析构函数:

当创建对象的块退出时,析构函数被隐式调用 [...] (8.7)

§4.1.1抽象机

该条款有时被称为“as-if”规则,因为只要结果就像是遵守了要求,就可以从可观察到的行为中确定,实现可以自由地无视本文档的任何要求。程序

[强调我的]

所以,是的。您的变量在循环结束时超出范围(这是一个块),因此只要观察程序行为的任何人都知道它的析构函数就会被调用。

  • @stark 允许他们这样做的是假设规则。该标准仅指定抽象机的行为。不确定是否有必要在此处的答案中详细介绍所有细节。 (2认同)
  • @stark,IMO,这与问题无关。您也可以说析构函数可能是内联的,因此根本不被“调用”。或者,如果它们实际上(假设规则)不执行任何操作,则可能不会生成此类析构函数的程序集。 (2认同)
  • @stark 请参阅[“假设”规则到底是什么?](/sf/ask/1100278371/)。 (2认同)
  • @stark在哪里定义了_what_?请注意,此讨论与问题无关。您可以就这个问题提出另一个单独的问题。 (2认同)

JBL*_*JBL 8

是的。当您考虑声明变量的“块”时,即在哪对大括号之间,更容易形象化。循环本身就是一个块,当它到达右括号时,在下一次迭代之前,循环中声明的自动存储变量的所有析构函数都会被调用。

编译器的循环展开可能会改变一些事情吗?

根据经验,不要考虑编译器会优化什么,因为它仍然需要保证程序的行为,无论它做什么来优化它。在这种情况下,如果发生循环展开,它不会改变任何效果。

  • 根据经验,+1,编写代码时不应担心编译器内部结构。本来想在我的答案中添加一些同样的内容,但现在它已经在那里了 (2认同)