AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 79566041
Accepted
HolyBlackCat
HolyBlackCat
Asked: 2025-04-10 15:54:42 +0800 CST2025-04-10 15:54:42 +0800 CST 2025-04-10 15:54:42 +0800 CST

变量正式是一个编译时概念吗?

  • 772

请注意,这是一个语言律师的问题。我知道“变量”的常见含义,但我想了解标准中对“变量”的具体定义。我正在编写一些教学材料,想使用正确的定义。


变量通常被定义为“命名对象”,或者更准确地说是“已声明的对象”(因为变量可以未命名,但总是被声明)。

但还有第二种观点认为变量是一个编译时概念。根据这种定义,源代码中的一个声明始终对应一个变量,即使在运行时从该变量创建了多个对象。

哪一个是正确的?


这里有一个例子来说明这一点。假设你有

void foo(bool a)
{
    int x = 42;

    if (a)
        foo(false);
}

当你调用时foo(true),两个 get 实例int x = 42;同时存在。

它们显然是两个不同的对象,但从技术上讲它们是不同的变量还是相同的变量?

如果变量是编译时的东西,那么两者就是同一个变量。


第二个定义从表面上看是错误的,但这里有一个 C++委员会成员认为它是正确的。

c++
  • 2 2 个回答
  • 203 Views

2 个回答

  • Voted
  1. Best Answer
    Davis Herring
    2025-04-10T20:34:00+08:002025-04-10T20:34:00+08:00

    尽管我的观点与所引用的观点并非完全独立,但我还是非常同意:标准中“变量”一词的含义更适合解释为“某些形式声明的抽象主体”,而不是“被视为具有特定类型的内存空间”。标准经常需要讨论变量的名称、声明变量的作用域、两个声明(可能在不同的翻译单元中)是否声明了同一个变量、一个变量是否是引用等等,而这些显然与单个翻译时构造有关,而不是与执行期间存在的任何事物有关。最后一点最有力的证据是,即使变量是函数中从未调用的非静态局部变量,所有关于变量可用于常量表达式的规则都适用。

    另一方面,“对象”一词的使用方式主要与“真实数据”概念相对应:它具有值和地址,并且可以处于或超出生命周期。这是有道理的,因为标准必须支持所有通过new(放置或其他方式)创建的对象上的运行时操作,而这些对象显然不是变量。

    不幸的是,标准在这方面并不完全一致,过于依赖读者对意图的直觉理解,例如“变量由对象的声明[…]引入。”([basic.pre]/7)和“具有自动存储期限的块变量[…]按声明顺序初始化”([stmt.dcl]/2)。目前已经取得了一些进展(C++17 不再将*this“实体”称为可以通过名称查找或其他方式找到的实体),并且还有更多进展即将到来(Reflection 论文正在做进一步的清理工作,因为想要描述其^^x含义)。

    • 4
  2. Yakk - Adam Nevraumont
    2025-04-10T22:31:58+08:002025-04-10T22:31:58+08:00

    C++ 标准(不完整地)指定了执行您编写的代码的抽象机器的行为。

    将其映射到实际硬件完全取决于编译器;只要生成的程序的行为“就像”是抽象机器一样,那么该程序就是符合要求的。

    这允许编译器执行诸如完全消除对象之类的操作,只要程序的行为“如同”该对象存在一样。程序运行的硬件上的实际位不受限制,除非在某些情况下与预期的位不一致是非常不切实际的。

    这种“as-if”选项通常在编译器几乎完全了解对象可能用途的情况下使用。例如,没有人检查指向局部变量的指针。标准规定某些操作是未定义行为(例如,在 C++ 中手动遍历堆栈就要求未定义行为);这意味着它可以证明没有人“合法地”访问过某个变量,因此可以消除该变量的存在(或将其更改为其他变量)。

    在你的示例程序中,没有人访问x,所以它在运行时不必存在。事实上,如果你检查优化编译器生成的代码,你会发现它确实缺失了。

    • 0

相关问题

  • 为什么编译器在这里错过矢量化?

  • 使用带有库的 CMake 编译错误[关闭]

  • 每次我尝试运行预制时都会抛出错误

  • 如何在 C++ 中创建类似于 std::byte 的八位字节类型?

  • C++17 中 std::byte 只能按位运算?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    重新格式化数字,在固定位置插入分隔符

    • 6 个回答
  • Marko Smith

    为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会?

    • 2 个回答
  • Marko Smith

    VScode 自动卸载扩展的问题(Material 主题)

    • 2 个回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Martin Hope
    Fantastic Mr Fox msvc std::vector 实现中仅不接受可复制类型 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant 使用 chrono 查找下一个工作日 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor 构造函数的成员初始化程序可以包含另一个成员的初始化吗? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský 为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul C++20 是否进行了更改,允许从已知绑定数组“type(&)[N]”转换为未知绑定数组“type(&)[]”? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann 为什么 {2,3,10} 和 {x,3,10} (x=2) 的顺序不同? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve