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



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

n4800

§6.3.3块范围

在块 (8.3( 中声明的名称是该块的本地名称;它具有块范围。它的潜在范围始于 声明点 (6.3.2( 并在其块的末尾结束。在块范围内声明的变量是局部变量 变量。

§10.3.6析构函数

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

§4.1.1抽象机

规定有时称为"假设"规则,因为实现可以自由地忽略此规则的任何要求。 记录,只要结果好像已经遵守了要求,只要可以从可观察的 程序的行为

[强调我的]

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

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

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

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

每次迭代都会调用析构函数。因此,在某些情况下,在循环外部声明变量比在循环中声明变量更快。 假设以下情况:

std::string temp;
for(int i = 0; i < 10; ++i){
temp = arr[i];
doSomething(temp);
}

执行使用循环时不调用析构函数。它只是覆盖temp.

但是,如果使用std::string temp = arr[i]则每次迭代都会调用构造函数和析构函数。 我认为这增加了一点运行时,以防您有一个经常执行的循环。

析构函数在下一次迭代之前调用

当然,dtor 是在迭代结束时调用的,循环展开不应该像任何其他优化(优化不应该修改程序行为(一样修改此行为,除了某种 RVO 等,它们可能会消除一些语义上虚假的对象创建。

最新更新