使用声明并初始化但未定义的变量是否是未定义行为?

问题描述 投票:0回答:2

在 C++ 中,您可以在

C
中声明一个类
c.h
,其中包含
static const int var = 3;
的声明和初始化。

class C {
public:
...
    static const int var = 3
...
};

除非您使该变量内联,或在您的

c.cpp

中显式定义它
...
const int C::var;
...

它是未定义的。

  • 所以,甚至在与内存地址无关的事物中使用
    var
    ,例如 for 循环中的计数器未定义行为?
  • 编译器如何使用未定义变量的值?做 预处理器宏替换它的值?
  • 除了类中的 static int 变量的这种情况 声明,是否还有其他情况可以让您 已声明并初始化但未定义的变量?
  • 这在 C 编程语言中会发生吗?

我知道必须有某种机制来实现这项工作,因为我见过使用未定义的静态 const 变量的 C++ 代码。但我希望引用该标准。

c++ static language-lawyer undefined-behavior
2个回答
2
投票

C 编程语言中会发生这种情况吗?

在 C 中,如果您在头文件中定义变量

static int var = 3;
,则包含此头文件的每个 C 源文件都将拥有自己的本地副本(如果定义了
var
)。不存在声明并初始化但未定义的变量

请注意,如果配置为生成有用的警告,编译器将报告未使用的

static
变量,因此您应该收到多个警告,除非您在每个源文件中都使用
var

Global

const
定义在 C 和 C++ 中的语义略有不同,但这是一个不同的问题。


0
投票

Per [class.static.data]/4 句子 1 仅当

var
具有
const
限定的整型或枚举类型并且由以下方式初始化时,才允许将静态数据成员的此构造作为一般规则的例外:常量表达式。

[class.static.data]/4 句子 2 需要

var
的定义,当且仅当
var
odr-used。否则该程序是 IFNDR(格式错误,无需诊断)。

通常,如果变量在潜在求值表达式中命名,则该变量始终是 odr-used。

但是,因为

var
const
整型或枚举类型,并使用常量表达式初始化,所以它可以在常量表达式中使用(并且不能有可变子对象),因此 [basic.def 中的异常即使 var
 在潜在评估的表达式中被命名,.odr]/4.2
也可能适用。如果您在表达式中对
var
所做的只是立即读取其值(左值到右值转换),而不是例如,则此异常本质上适用。形成指向它的指针/引用。因为变量是用常量表达式初始化的,所以编译器可以将变量的使用替换为给
var
的编译时常量值。

[basic.def.odr]/4.3 中还有另一个小例外,即变量基本上立即被命名为丢弃值表达式,例如当写

var;
作为陈述时。在这种情况下,编译器不需要
var
的值和地址。

这些都与预处理器无关,预处理器甚至在解析实际 C++ 代码之前就专门工作。

我认为这是唯一的例外,您可以对变量进行初始化声明,但同时又不能对其进行定义。它仅因历史原因而存在,因为之前

constexpr
inline
可用于变量以使静态数据成员的值可在常量表达式中使用。

© www.soinside.com 2019 - 2024. All rights reserved.