首页 > 解决方案 > 丢弃一个值会导致读取它吗?

问题描述

考虑以下示例:

{
  int x;
  (void)x; // silence the "unused" warning
  ...
}

x由于未初始化读取,这是否会导致未定义的行为?如果是,那么这是否意味着在以下代码中必须由编译器发出内存读取指令(读取指针)?

volatile char* p=getP();
(void)*p;

我对这方面的 C 和 C++ 规则都感兴趣,以防它们不同。

标签: c++clanguage-lawyer

解决方案


在 C++ 中,访问与左值到右值的转换相结合。这种转换需要一个“身份”并产生它的价值。关于丢弃值表达式的主题,C++ 标准是这样说的:

[expr](强调我的)

12在某些情况下,表达式的出现只是因为它的副作用。这样的表达式称为弃值表达式。不应用数组到指针和函数到指针的标准转换。当且仅当表达式是 volatile 限定类型的左值并且它是以下之一时,才应用左值到右值的转换

  • ( 表达式 ),其中表达式是这些表达式之一,
  • 身份表达,
  • 下标,
  • 类成员访问,
  • 间接,
  • 指向成员的操作,
  • 条件表达式,其中第二个和第三个操作数都是这些表达式之一,或者
  • 逗号表达式,其中右操作数是这些表达式之一。

[注意:使用重载运算符会导致函数调用;以上仅涵盖具有内置含义的运算符。— 尾注] 如果在此可选转换之后表达式是纯右值,则应用临时实现转换。[ 注意:如果表达式是类类型的左值,它必须有一个 volatile 复制构造函数来初始化作为左值到右值转换的结果对象的临时对象。— 尾注] 对 glvalue 表达式求值并丢弃它的值。

在非易失性情况下,没有左值到右值的转换。因此,我们可以自信地说该变量未被访问

但是,在 volatile 情况下,您在强制转换表达式内部具有间接性,并且会进行左值到右值的转换。因此,将读取 volatile 并且您会从读取未初始化的对象中获得未定义的行为。

为了避免 volatile glvalues 周围的未定义行为,可以将相关变量注释为[[maybe_unused]]. 这是认可的方式,也是我更喜欢在非易失性案例中使用演员的方式。


推荐阅读