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

Is the destructor of a local object inside a loop guaranteed to be called before the next iteration?

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

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

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

might loop unrolling by the compiler change something about that?

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

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

来自 n4800:

§6.3.3 块作用域:

A name declared in a block (8.3) is local to that block; it has block scope. Its potential scope begins at its point of declaration (6.3.2) and ends at the end of its block. A variable declared at block scope is a local variable.

§10.3.6 析构函数:

A destructor is invoked implicitly [...] when the block in which an object is created exits (8.7)

§4.1.1 抽象机:

This provision is sometimes called the “as-if” rule, because an implementation is free to disregard any requirement of this document as long as the result is as if the requirement had been obeyed, as far as can be determined from the observable behavior of the program.

[强调我的]

所以,是的。您的变量在循环结束时超出范围(这是一个块),因此它的析构函数被称为 任何观察程序行为的人都可以告诉 .

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

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

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

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