string - for 循环中的变量在每次迭代时都没有重新初始化?

标签 string c++-cli scope

我有一个 C++/CLI 项目,它在 for 循环中声明了一个 String^ 变量,但没有对其进行初始化。在第一次迭代中,变量被设置为某个值。在随后的每个 迭代,它似乎保留了以前的值。每次循环时,局部作用域中的变量是否都不应初始化为 null(或等效值)? int 也会发生这种情况。另外,编译器 除非我将警告级别设置为 W4,否则不会警告可能未初始化的值,即使这样它也只会警告 int 而不是 String^。

这是显示行为的示例代码。

#include "stdafx.h"
using namespace System;

int main(array<System::String ^> ^args)
{
    for(int n = 0; n < 10; n++)
    {
        String^ variable;
        int x;

        switch(n)
        {
        case 1:
            variable = "One";
            x = 1;
            break;
        case 5:
            variable = "Five";
            x = 5;
            break;
        }

        Console::WriteLine("{0}{1}", variable, x);
    }
}

这个的输出将是

One, 1
One, 1
One, 1
One, 1
Five, 5
Five, 5
Five, 5
Five, 5
Five, 5

我是否完全误解了应该如何初始化局部范围的变量?这是托管 C++ 独有的“功能”吗?如果我转换 这对于 C# 来说,编译器将对这两个变量发出警告,即使是在基本警告级别。

最佳答案

免责声明:我非常了解 C 和 C++; C++/CLI,没那么多。但是您看到的行为与我对 C 或 C++ 中的类似程序的预期基本相同。

String^String句柄,类似于 C 或 C++ 中的指针

除非 C++/CLI 添加新的句柄初始化规则,否则没有显式初始化的 String^ 类型的 block 作用域变量最初将具有垃圾值,由其中发生的任何内容组成大块内存。

循环的每次迭代在概念上都会创建和销毁 {} 之间定义的任何变量。并且每次迭代可能 都在相同的内存位置分配其局部变量(这不是必需的,但没有真正的理由不这样做)。编译器甚至可以生成在函数入口处分配内存的代码。

因此在循环的第一次迭代中,variable 被设置为 "One"(或者更确切地说,设置为指向 "One"< 的句柄),这是 Console::WriteLine 打印的值。没问题。

在第二次迭代中,variable 被分配到与第一次迭代相同的内存位置。没有为其分配新值,因此它保留了第一次迭代时存储在该内存位置的值。 x 也会发生同样的事情。

您不能指望保留以前的值,并且您的程序的行为是未定义的。如果您的目标是编写一个正确运行的程序,而不是了解这个错误程序的行为方式,那么解决方案是确保所有变量在使用前都已正确初始化。

如果您在第二次迭代而不是第一次迭代时进行初始赋值,程序可能会在第一次迭代时崩溃——尽管这并不能保证。

至于为什么编译器不警告这个,我不知道。我对提出编译器错误犹豫不决,但这可能是一个。

此外,即使启用了高警告级别,关于未初始化变量的警告也需要控制流分析,而这可能不会在默认情况下进行。启用警告 高级优化可能会为编译器提供足够的信息来警告 variablex

它警告 x 而不是 W4variable 似乎仍然很奇怪。

关于string - for 循环中的变量在每次迭代时都没有重新初始化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13883142/

相关文章:

ios - XCode,字符串编码,西里尔字母

C++ 模板化函数调用托管函数

javascript/jquery 范围让我难住了

rust - 在 Rust 中,Box :ed struct compared to a plain struct? 的放置顺序是否存在差异

java - For循环类型比较

string - 如何在 WP7 中从字符串中删除重音符号

c# - 如何将 C++ 代码包装到具有大量 float*(代表点)的 CLI 中?

javascript - 更改 setTimeout 上的匿名函数的范围会导致奇怪的警告

java - 在不分配字符串的情况下在Java中将字符串转换为int

.net - `finally` 代码块可能被跳过的原因是什么?