当前位置: 首页 > 知识库问答 >
问题:

在主存循环中分配局部变量

卫俊力
2023-03-14

假设我有一个for循环,其中有一个局部变量:

for(int i=0;i<10;i++){ // Outer loop

    int p[10]; // Local variable

    for(int j=1;j<10;j++){ // Inner loop
    
        p[j] = p[j-1]+1;
    }
}

当所有编译器优化都关闭时,很明显,对于外部循环的第一次迭代,将在主内存中分配一个数组p

但是,分配给p的内存是否在外循环的第一次迭代结束时在主内存中释放,并在外循环的后续迭代开始后再次分配?

在我看来,循环的范围和方法的范围是不同的。当函数完全执行后,局部变量将被释放,内存将返回给操作系统。

但是对于循环,当作用域在每次迭代结束时结束时,局部变量不会被释放,因为它们是在不久的将来(后续迭代)使用的。只有在循环结束它的执行之后,局部变量才应该从主内存中释放。

如果错了请指正。

共有2个答案

云星波
2023-03-14

p的作用域是外部循环,因此在每次迭代时都会在堆栈上销毁并重新创建它。唯一没有被破坏的变量是i,但直到完成外部循环。int p[10];i=0时int p[10]不同;i=1时等,因此i=1时,先前的p已经消失。任何其他优化(或假设)都依赖于编译器、体系结构等。

要说明的是,p位于堆栈上,它的作用域将决定何时释放内存(与堆上的变量不同)。

可能有点吹毛求疵,但使用现代C++容器,如std::arraystd::vector,而不是原始的普通C数组。

要改进资源管理,请查看RAII。

齐振
2023-03-14

C++的行为是以抽象机器的形式定义的。在这台机器中,具有自动存储持续时间的对象的存储器保证从每次进入块的开始(块中代码的执行开始)一直存在到块的执行结束。与int p[10]关联的块是由{for(int i=0;i<10;i++)之后立即创建的块。此块的执行在for循环的每次迭代中开始和结束。

尽管编译器很可能通过分配堆栈空间一次来实现这个循环(可能是在它所在的函数启动时,而不是到达for循环时),因此用于实现int p[10]内存仍然分配给整个循环,而不是每次迭代,但程序的行为是根据抽象机器定义的。

这意味着尽管堆栈空间仍然保留,但编译器的优化不需要这样做。优化可能导致代码在迭代中“忘记”p元素中的值。

例如,如果我们使用Apple Clang 11.0在macOS 10.14.6上使用-o3-std=C++17执行此代码:

    int p[10];
    for (int i = 0; i < 10; i++)
    {
        if (i == 0)
            p[0] = 0;
        else
            p[0] = p[0]+1;
        for (int j = 1; j < 10; j++)
        {
            p[j] = p[j-1] + 1;
        }
        if (i == 9)
            std::cout << p[0] << '\n';
    }

那么输出为“9”,因为p[0]在第一次迭代中被设置为0,并在以后的每次迭代中递增。但是,我们将int p[10];移动到循环内部,输出为“0”,因为编译器优化没有在迭代之间保留p[0]的值。

 类似资料:
  • 问题内容: 我正在尝试解决一个任务(我对Java还是很陌生),并且已经花了很多资源来解决此冲突,但是仍然无法解决(注意:Tuna是我的Scanner变量) } 结果是:线程“ main” java.lang.Error中的异常:未解决的编译问题:重复的局部变量计数 我应该解决的问题是: 编写程序以读取一个数字并将所有数字从1汇总到该数字。例如,如果用户键入6,则输出为21(1 + 2 + 3 +

  • 问题内容: 我刚刚遇到了这段代码 并且认为, 必须 有一个比用无限循环更好的方法。 所以我尝试了: 显然有一个错误。 有什么方法可以避免在那种情况下使用? 编辑: 理想情况下,您要避免重复说两次…恕我直言,重复甚至比a还要糟糕,尤其是在语句很复杂的情况下。 问题答案: 如果您不对数据做任何奇特的事情,例如以后再阅读更多行,总会有:

  • 问题内容: 我有一个关于变量范围的相当简单的问题。 我对增强型循环很熟悉,但是我不明白为什么我应该声明一个新变量来保留每个元素。一个例子可以澄清我的问题: 那为什么要声明这个新变量呢?毕竟在for循环内是可访问的。我不想使用任何先前的值,只是不想声明一个新变量。(我猜想对于其他可迭代项,使用相同变量可能会更快)。 我想这就是增强型循环的构建方式,但这不会破坏整个范围的想法吗? 上述行为引起了一个问

  • 问题内容: 我想知道你们是否可以提供帮助。我试图做一个简单的视图,它将用户发送到客户端创建表单,但是我一直收到此错误: 赋值之前引用的局部变量“ form” 查看我的代码,看不到有什么问题。 有人告诉我我哪里出问题了吗? 问题答案: 这是正在发生的事情: 没有输入该块。 变量未定义。 然后,你尝试在语句中引用变量。 至于解决方法,这确实是你要决定的。解决的方法取决于你希望代码执行的操作(如果请求方

  • 问题内容: 我相信在AS3中,您应该在循环外初始化所有变量,以提高性能。JavaScript也是如此吗?哪个更好/更快/最佳实践? 要么 问题答案: 有 绝对没有区别 意义还是性能,在JavaScript或ActionScript。 是解析器的指令,而 不是 运行时执行的命令。如果在函数体(*)中的任何位置一次或多次声明了特定的标识符,则该标识符在块中的所有使用将引用局部变量。声明是在循环内部,循

  • 问题内容: 我有一个座位数组,该数组有两个字符串(已选择和为空)。单击鼠标后,我想遍历数组并找到选定的座位。当我按下按钮时,它说: 无法分配最终的局部变量seatno,因为它是用封闭类型定义的。 问题答案: 关键是封闭类型中的方法局部变量实际上已 复制 到匿名类的实例中(这是由于激活框架的问题,但我将不做进一步的详细介绍,因为这与问题无关)。这就是为什么它们需要是final的原因,因为嵌套类型实例