为什么在循环内声明变量并不意味着每次进入循环时都重新声明变量

2024-03-31

int main()
{
    int x;
    int x;
    return 0;
}

这段代码会报错:

错误:重新声明“int x”

但这一个,效果很好:

int main()
{
    while(true)
    {
        int x;

        {...}
    }
    return 0;
}

这就是为什么在第二个示例中,在循环中声明 x 不会在每次迭代时重新声明它的原因?我期待与第一种情况相同的错误。


你将两个相关但不同的概念混在一起,因此你感到困惑。但这不是你的错,因为大多数关于这个问题的教学材料不一定能清楚地阐明这两个概念之间的区别。

  1. 变量范围:这是源代码中符号(变量)可见的区域。

  2. 对象生命周期:这是程序运行时对象存在的时间。

这给我们带来了需要理解和区分的其他两个概念:

  1. 一个变量是一个编译时概念:它是引用对象的名称(符号)
  2. 一个东西是运行时的“实体”,是类型的实例。

让我们回到你的例子:

int main()
{
    int x{};
    int x{};
}

在这里,您尝试在同一范围内声明 2 个不同的变量。这两个变量在函数作用域内具有相同的名称,因此当您“说出”名称时x(当你写下符号x)你不知道你会引用哪个变量。所以这是不允许的。

int main()
{
    while(true)
    {
        int x{};
    }
}

在这里,您在 while 主体范围内声明了一个变量。当你写的时候x在此范围内,您引用​​此变量。没有歧义。没问题。有效代码。请注意,有关声明和变量范围的讨论适用于编译时,即我们正在讨论您编写的代码的含义。

然而,当我们讨论对象生命周期时,我们谈论的是运行时,即编译的二进制文件运行的那一刻。是的,在运行时,会连续创建和销毁多个对象。所有这些对象都由符号引用x在 while 主体范围内。但这些对象的生命周期不要重叠。 IE。当您运行程序时,将创建第一个对象。在源代码中它被命名为x在 while-body 范围内。然后该对象被销毁,重新进入循环并创建一个新对象。它也被命名为x在 while-body 范围内的源代码中。然后销毁,重新进入while,创建一个新对象等等。


为了让您对此事有更广泛的了解,请考虑您可以:

从未引用对象的变量

{ // not global scope
    int a; // <-- not initialized
}

变量a未初始化,因此永远不会在运行时创建对象。

没有名称的对象:

int get_int();

{
    int sum = get_int() + get_int();
}

两次调用该函数返回两个对象get_int()。这些对象是临时的。他们从未被命名。

在变量范围内实例化多个对象。

这是一个高级的、人为的示例,位于 C++ 的边缘。只是表明这在技术上是可行的:

{

    int x;

    // no object

    new (&x) int{11};  // <-- 1st object created. It is is named `x`. Start of its lifetime

    // 1st object is alive. Named x

    x.~int(); // <-- 1st object destructed. End of its lifetime

    // no object

    new (&x) int{24};  // <-- 2nd object created. Also named `x`

    // 2nd object alive. Named x

} // <-- implicit end of the lifetime of 2nd object. 

范围x是由大括号分隔的整个块。然而,在此范围内有两个具有不同的非重叠生命周期的对象。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么在循环内声明变量并不意味着每次进入循环时都重新声明变量 的相关文章

  • .pdbs 会减慢发布应用程序的速度吗?

    如果 dll 中包含 pdb 程序调试 文件 则行号将出现在引发的任何异常的堆栈跟踪中 这会影响应用程序的性能吗 这个问题与发布与调试 即优化 无关 这是关于拥有 pdb 文件的性能影响 每次抛出异常时都会读取 pdb 文件吗 加载程序集时
  • libtool 在 Ubuntu 13.04 上构建 thrift 0.9.1 时出错

    在 Ubuntu 13 04 上构建 thrift 0 9 1 支持 C C java C perl python 时出现此错误 configure 不带任何选项运行 make 不带任何选项运行 Making all in test mak
  • C# Outlook 从收件人获取 CompanyName 属性

    我目前正在使用 C 编写 Outlook 2010 AddIn 我想要的是从我从 AppointmentItem 中提取的 Recipient 对象中获取 CompanyName 属性 因此 有了 AppointmentItem 的收件人
  • C++中的类要具备什么条件才能成为容器?

    我是 C 编程新手 偶然发现了这个术语containers举例如下vector deque map etc 一个企业的最低要求应该是什么class应该满足被称为container in C 我将从 范围 这个概念开始 Range 只有两个方
  • DataGridView 列中的数字文本框

    我有一个DataGridView 我想要它的第一列或任何所需的列 其中有textboxes在其中 成为NUMERIC ONLY 我目前正在使用这段代码 private void dataGridViewItems EditingContro
  • 从时间列表中查找最接近的时间

    所以 这是场景 我有一个带有创建时间的文件 我想从该文件的创建时间最接近或相等的时间列表中选择一个时间 完成此操作的最佳方法是什么 var closestTime listOfTimes OrderBy t gt Math Abs t fi
  • Nhibernate:连接表并从其他表获取单列

    我有以下表格 create table Users Id uniqueidentifier primary key InfoId uniqueidentifier not null unique Password nvarchar 255
  • C# Winforms Designer 无法打开,因为它无法在同一程序集中找到类型

    我收到以下错误 找不到类型 My Special UserControl 请确保引用包含此类型的程序集 如果此类型是您的开发项目的一部分 请确保已使用当前平台或任何 CPU 的设置成功构建该项目 但没有任何意义的是My Special Us
  • 检测 TextBox 中的 Tab 键按下

    I am trying to detect the Tab key press in a TextBox I know that the Tab key does not trigger the KeyDown KeyUp or the K
  • 如何在新窗口中打开图像或pdf文件?

    我有一个 gridview 它包含文件名和文件路径 图像和 pdf 格式文件 其中我使用了模板字段 在该字段下放置了 1 个图像按钮 单击该图像按钮 即 查看 按钮 时 我想在新窗口中打开所选文件 这是我的代码 protected void
  • 如何在 EF Core 2.1 中定义外键关系

    我的 DAL 使用 EF Core 2 1 这就是我的模型的样子 一名用户只能拥有一种角色 Role entity kind of master public class Role public int RoleId get set pub
  • MSChart 控件中的自定义 X/Y 网格线

    我有一个带有简单 2D 折线图的 C Windows 窗体 我想向其中添加自定义 X 或 Y 轴标记 并绘制自定义网格线 例如 以突出显示的颜色 虚线 我查看了 customLabels 属性 但这似乎覆盖了我仍然想显示的默认网格 这是为了
  • 在 mvc4 中创建通用 mvc 视图

    我以前也提过类似的问题 没有得到答案 如何创建一个通用的 mvc4 视图 该视图可以显示传递给它的模型列表或单个模型 模型可以是个人 组织或团体 无论传递给它的是什么 如果您正在寻找类似的东西 model MyViewModel
  • WPF DataGrid - 在每行末尾添加按钮

    我想在数据网格的每一行的末尾添加一个按钮 我找到了以下 xaml 但它将按钮添加到开头 有人知道如何在所有数据绑定列之后添加它吗 这会将按钮添加到开头而不是末尾
  • 如何测试某些代码在 C++ 中无法编译? [复制]

    这个问题在这里已经有答案了 可能的重复 单元测试编译时错误 https stackoverflow com questions 605915 unit test compile time error 我想知道是否可以编写一种单元测试来验证给
  • 如何调用与现有方法同名的扩展方法? [复制]

    这个问题在这里已经有答案了 我有这样的代码 public class TestA public string ColA get set public string ColB get set public string ColC get se
  • 初始化列表在 VC10 中不起作用

    我在 VC 2010 中编写了这个程序 class class1 public class1 initializer list
  • 对多个对象使用事件处理程序

    我有 20 件物品List
  • 在 C 中使用 #define 没有任何价值

    If a define没有任何价值地使用 例如 define COMMAND SPI 默认值是0吗 不 它的评估结果为零 从字面上看 该符号被替换为空 然而 一旦你有了 define FOO 预处理器条件 ifdef FOO现在将是真的 另
  • Emacs C++,打开相应的头文件

    我是 emacs 新手 我想知道 是否有在头文件 源文件和相应的源文件 头文件之间切换的快捷方式 是否有像通用 emacs 参考卡那样的参考卡 Thanks There s ff find other file 您可以使用以下方法将其绑定到

随机推荐