【问题标题】:C++ variable declaration in a loop and runtime error循环中的 C++ 变量声明和运行时错误
【发布时间】:2014-03-09 00:06:52
【问题描述】:

我有一个在循环中声明的缓冲区。它在第一次迭代时被初始化。我最近在 Visual Studio 2010 调试中运行了代码,它在运行时错误时中断:
Run-Time Check Failure #3 - The variable 'buffer' is being used without being initialized.

这里是一些示例代码。 It's also available on ideone where it runs successfully.

using namespace std;
int main( int argc, char *argv[] )
{
    for( int i = 0; i < 5; ++i )
    {
        char buffer[5];
        if(i == 0)
        {
            buffer[0] = 'y';
            buffer[1] = '\0';
        }
        cout << buffer[0] << endl;
    }

    return 0;
}

我认为缓冲区不是在每次迭代时都重新创建的。我知道如果我有一个向量或其他东西,那么每次迭代都会调用构造函数,但我认为 C 类型或 POD 类型(如果这是正确的短语的话)是不同的。

Visual Studio 是正确还是错误,我有很多地方在循环的迭代 n 中更改了缓冲区,并且我希望该缓冲区在之后的迭代中相同,直到再次更改。他们在 gcc 中,但在最近的调试会话中,我猜这只是运气!

谢谢

编辑:在 codeguru 上发现了一个有趣的帖子,人们似乎对此意见不一:
Variable declaration inside a loop

【问题讨论】:

  • 想知道您是如何想到存在“特殊情况”的。所有自动变量都以相同的方式处理,这是一件好事。
  • 如果有void f(int b) { int a = b; },那么每次调用函数时都会为变量a创建一个对象。没有什么特别的事情发生。对象是动态概念;变量是静态概念。变量在源代码中,对象在运行程序中。单个变量声明会导致许多对象的生命,这并不矛盾。

标签: c++ visual-studio-2010 gcc visual-studio-debugging


【解决方案1】:

变量从它被声明的那一刻起一直存在到它被声明的范围的末尾。你的编译器是对的。只有在循环的i == 0 循环中,buffer 变量才被初始化(部分);在所有其他循环中,变量保持未初始化。

情况和这个没有什么不同:

{
    int n = 10;
}

{
    int n;      // uninitialized
    cout << n;  // UB
}

【讨论】:

  • 我认为你的例子有缺陷。编译器将其标记为未初始化的原因是 if 语句。
  • @CaptainGiraffe:我不明白。编译器将其标记为未初始化的原因是因为它未初始化。
  • 不同之处在于,如果语义检查包括运行时后果,则 OP 的代码可能是有效的。
  • @CaptainGiraffe:OP 的代码永远无效。编译器是对的。
  • 没错,但他的困惑是有道理的。很遗憾,我无法提供更好的答案。
【解决方案2】:

如果您希望变量在 for 循环中保留其值,您应该始终在外部声明它。不管是类还是POD。

这最能向编译器和您的软件维护人员表达您的意图。 通过将其移动到 for 循环中,您几乎一无所获。 如果你决心让所有人都知道这个 var 只用在 for 循环作用域中,那么你可以在它周围添加另一个作用域。

using namespace std;
int main( int argc, char *argv[] )
{
    {
        char buffer[5];
        for( int i = 0; i < 5; ++i )
        {
            if(i == 0)
            {
                buffer[0] = 'y';
                buffer[1] = '\0';
            }
            cout << buffer[0] << endl;
        }
  }
  return 0;
}

考虑到某些编译器可能会为您优化循环外的初始化,这会使代码不清楚。标准中也没有说明这种优化,因此编译器可以不这样做。

【讨论】:

  • 谢谢你的例子。另一位发帖人先给出了正确答案,所以我将他的答案标记为正确。
猜你喜欢
  • 1970-01-01
  • 2011-12-23
  • 2016-02-23
  • 2018-10-11
  • 2012-06-25
  • 2017-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多