为C++中的循环在内部定义的局部变量

Local variables defined inside for loops in C++

本文关键字:定义 局部变量 在内部 循环 C++      更新时间:2023-10-16

在以下C++代码中:

for (int i=0; i<10; i++)
{
int y = someFunctionCall();
//Some statements
}

变量(y)是在每次循环迭代时分配,然后在迭代完成时取消分配,还是为所有循环迭代分配一次?

上述代码是否等效于以下代码?:

int y;
for (int i=0;i<10;i++)
{
y = someFunctionCall();
//Some statements
}

当函数被调用时,它将在堆栈上分配一次。就性能而言,这两种方法没有区别(但请记住,使用最后一种方法,y在循环后仍将在作用域中)。变量似乎是在每次迭代之间创建和销毁的(因此它在迭代之间"丢失"了值)是编译器创建的行为;实际的存储器位置始终是相同的。

它不是每次都分配的,但在每次迭代中都会分配一个新值。循环在一个方法中,该方法有自己的堆栈框架。变量y是在堆栈帧中分配的。

循环中的每个循环都会创建一个新变量。

但是,对于int类型的变量,这并不重要。变量的作用域最好较小。编译器可能足够聪明,每次都可以重用相同的空间。

我认为每次进入循环时都会在堆栈上分配变量y,因为当变量离开此范围时,它将被删除。

它不可能与您提供的等价,因为y不在for循环的范围内。

但这一切实际上都取决于编译器,如果这是你想要的,你必须衡量两者之间的性能。

代码中的y是一个局部变量。尽管许多人认为这些没有分配。它们可能在堆栈上为它们保留了一些空间,也可能没有,但只有在优化后,它们的地址被占用时,才能保证这一点。

在所有其他情况下,它们可能根本没有在堆栈上保留空间。或者,堆栈上可能有一些空间供它们使用,但相同的空间可用于多个变量,甚至在某些情况下,用于将参数传递给正在调用的函数。

当在堆栈上保留空间时(可能发生也可能不发生),通常在函数进入时立即保留空间。然而,这是一个实现细节。这样做是因为这是最快的方法。不需要这样做,而且一个实现可以很好地动态改变当前堆栈帧的大小(在大多数现代处理器上,这样做是愚蠢的,但这样的实现仍然是正确的)。

对于内部构建类型,这并不重要(无论可见性的范围如何)。对于对象,对象变量是否在for循环中保持不变(!)很重要。考虑以下内容:

#include <iostream>
struct A
{
static int i;
void * a;
A() : a(this) { ++i; }
};
int A::i = 0;
int main()
{
for (int i = 0; i != 10; ++i)
{
A a;
std::cout << a.a << " | " << a.i << std::endl;
}
return 0;
}