在循环完成后,循环内的变量(while或for)是否已处理?

Dan*_*and 16 c++ variables

在循环执行完毕后,是在while内部创建的变量还是for循环中的变量?另外,在循环中创建临时变量是一种糟糕的编码习惯吗?

在这个例子中,它是创建100个X变量然后处理它们,还是在每次迭代时都处理它们?谢谢.例:

int cc =0;
while(cc < 100){
    int X = 99; // <-- this variable
    cc++;    
}
Run Code Online (Sandbox Code Playgroud)

Kei*_*son 23

范围寿命是两回事.对于在块范围内定义的变量static,它们或多或少地紧密相连,但它们仍然是不同的概念 - 如果你不保持直线,你可以用脚射击自己.

从问题中引用代码段:

int cc =0;
while(cc < 100){
    int X = 99; // <-- this variable
    cc++;    
}
Run Code Online (Sandbox Code Playgroud)

范围X是在它的名称是可见的程序文本的区域.它从它定义的点延伸到封闭块的末尾,封闭块由{}字符分隔.(块恰好是while语句的一部分这一事实并不直接相关;它是定义范围的块本身.)

在块内,名称X指的是该int变量.在块外,名称X不可见.

寿命X是,当在程序执行期间的时间X在逻辑上存在.它在执行到达开始时{(定义之前)开始,并在执行到达结束时结束}.如果块被执行100次,则X创建并"销毁"100次,并且具有100个不相交的寿命.

虽然名称 X仅在其范围内可见,但可以在其生命周期内的任何时间(直接或间接)访问被调用的对象X.例如,如果我们传递&X给一个函数,那么该函数可以读取和更新该对象,即使该函数完全超出其范围.

您可以获取地址X,并保存该地址,以便在其生命周期结束后使用 - 但这样做会导致未定义的行为.指向生命周期结束的对象的指针是不确定的,任何取消引用它的尝试 - 甚至是指向指针的值 - 都有未定义的行为.

当一个对象到达其生命周期的末尾时,实际上不会发生任何事情.语言只需要对象在其生命周期中存在; 除此之外,所有赌注都已关闭.分配用于保存对象的堆栈空间可能被解除分配(这通常仅意味着移动堆栈指针),或者,作为优化,堆栈空间可能保持分配并重新用于循环的下一次迭代.

另外,在循环中创建临时变量是一种糟糕的编码习惯吗?

一点也不.只要您不将对象的地址保存到其生命周期的末尾,就没有任何问题.作为性能优化,分配和释放通常在进入和退出函数而不是块时完成.将变量限制在合理的范围内是一种非常好的编码习惯.它通过限制代码的不同部分之间不必要的交互来使代码更容易理解.如果X在循环体内定义,则循环外部的任何内容都不会影响它(如果你没有做过一些太棘手的事情),这使得更容易推理代码.

更新:如果X用一个非平凡的构造和/或析构函数的类型,创建和破坏X实际上有要在进入和退出从块执行(除非编译器能够以优化代码的距离).对于类型的对象int,这不是问题.


Fre*_*ame 6

是的,变量被创建和销毁N次,除非编译器以某种方式对其进行优化(我相信它可以).int虽然你只有一个,但这并不是什么大问题.当你在循环中重新创建99次复杂对象时,它会变得更有问题.

一个小实际的例子:

#include <iostream>
using namespace std;

class TestClass
{
public:
    TestClass();
    ~TestClass();
};
TestClass::TestClass()
{
    cout<<"Created."<<endl;
}

TestClass::~TestClass()
{
    cout<<"Destroyed"<<endl;
}

int main() {
    for (int i = 0; i < 5; ++i)
    {
        TestClass c;
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在此代码TestClass c中将重新创建5次.IdeOne演示.

  • 我最喜欢的答案。+1 用于解释带有对象构造函数/析构函数的示例。 (2认同)

JoE*_*anO 5

是的。范围内定义的任何变量{ }

if (true) { // Forgive me father for this heresy :)
    int a = 0;
}
a = 1; // This will throw an error
Run Code Online (Sandbox Code Playgroud)

一旦超出范围,就会自动解除分配。

在这种情况下也是如此:

for (int i = 0; i < 10; ++i) {
    // Do stuff
    ...
}
i = 1; // This will throw an error
Run Code Online (Sandbox Code Playgroud)

的范围i仅限于 for 循环,即使它没有在一对{ }.