理论上,每次变量进入作用域时,堆栈上的绝对位置都会被分配,每次超出作用域时都会释放它。然后分配堆栈的LIFO特性确保每次都分配相同的位置。
但实际上,只要这样做是实用的(在这种情况下是平凡的),编译器在编译时分配堆栈上的相对位置。通过预先分配的相对位置,进入函数的简单行为可以有效地分配所有局部变量的所有实例。像这样的循环中的局部对象将针对每个实例被构造和/或初始化,但是对于所有实例预先分配一次。因此,地址与堆栈的LIFO特性相比更为根本的原因是相同的。他们是一样的,因为分配只做了一次。
如果您的C++编译器支持通用的C99功能,则可以构建可区分上述两种情况的测试。事情大致是这样:
for (int i=0; i<2; ++i) {
int unpredictable[ f(i) ];
for (int j=0; j<2; ++j) {
int T=5;
// does the location of T vary as i changes ??
int U[ f(j) ]; // I'm pretty sure the location of U varies
}}
我们希望f的值(0)和f(1)很容易在运行时间,但很难优化看到在编译时。如果在此模块中声明了f,但在另一个模块中定义了f,则这是最稳健的。
通过阻止编译器在编译时完成所有的分配,我们可以阻止它在编译时进行一些简单的分配,或者仍然可以在编译时和运行时分配它们分配仅在需要时使用。
来源
2015-09-25 12:54:17
JSF
而在第二种情况下,分配的内存被泄漏,所以它*有*每次得到一个新地址 –
@BoPersson的权利,第二种情况是在我回答后添加的。将其包含在答案中。 – anderas