c++ - 是否通过未初始化的指针 UB 访问静态类成员?
问题描述
这个问题的后续问题
我们有以下代码:
#include <iostream>
struct A
{
static int n;
};
int A::n = 5;
int main()
{
A* a; //uninitialized on purpose
std::cout << a->n; //UB?
}
这种访问是一种未定义的行为吗?一方面,不需要对象来访问静态类成员,另一方面,operator->
未初始化的指针是自找麻烦。
注意:GCC 和 MSVC 编译此代码时没有任何警告,Clang 抱怨未初始化的使用。https://godbolt.org/z/Gy5fR2
解决方案
a->n
因为数据成员是静态的,所以*a
被评估但不被访问的语义。参见 C++17 [expr.ref]:
... 计算点或箭头之前的后缀表达式 ... 表达式
E1->E2
转换为等效形式(*(E1)).E2
...
还有一个脚注说:
如果评估类成员访问表达式,则即使结果对于确定整个后缀表达式的值不是必需的,例如如果 id-expression 表示静态成员,也会发生子表达式评估。
在这种情况下,表达式*a
被计算。由于a
是一个尚未初始化的自动变量,因此 [dcl.init]/12 适用:
如果评估产生不确定的值,则行为未定义,但以下情况除外: [ ... ]
评估*a
显然需要访问指针变量的值a
,这是一个不确定的值,因此它是UB。
推荐阅读
- git - git存储库未在intellij中加载
- python - 如何分组和绘制聚合数据?
- machine-learning - 深度神经网络模型在一个 epoch 后停止学习
- batch-file - 无明显原因关闭批处理文件
- python - 如何在tensorflow中重用操作?
- python - 具有实际环境而不是 python 类环境的 TensorFlow 代理
- apache-kafka - 删除 Kafka/log 旧文件是否安全?
- python - 如何让我的函数在以下代码中在 tkinter 中配置正确的标签?
- javascript - 如何自动化应用程序脚本中的特定范围
- java - 错误:不兼容的类型:从 double 到 float 的可能有损转换