Rus*_*lan 7 c c++ language-lawyer
考虑以下示例:
{
int x;
(void)x; // silence the "unused" warning
...
}
Run Code Online (Sandbox Code Playgroud)
是否由于x未初始化读取而导致未定义行为?如果是,那么这是否意味着在以下代码中,编译器必须发出内存读取指令(以读取指针)?
volatile char* p=getP();
(void)*p;
Run Code Online (Sandbox Code Playgroud)
我对这方面的C和C ++规则都感兴趣,以防它们有所不同。
在 C++ 中,访问与左值到右值的转换相结合。这种转换就是获取“身份”并产生其价值的过程。关于丢弃值表达式的主题,C++ 标准是这样说的:
\n\n\n\n\n[expr](强调我的)
\n\n12在某些上下文中,表达式仅因其副作用而出现。这样的表达式称为丢弃值表达式。\n 不应用数组到指针和函数到指针的标准转换。当且仅当表达式是 volatile 限定类型的左值并且是以下其中一项时,才会应用左值到右值的转换:
\n\n\n
\n\n- ( 表达式 ),其中表达式是这些表达式之一,
\n- id-表达,
\n- 下标,
\n- 类成员访问,
\n- 间接,
\n- 指向成员的指针操作,
\n- 条件表达式,其中第二个和第三个操作数都是这些表达式之一,或者
\n- 逗号表达式,其中右操作数是这些表达式之一。
\n[\xe2\x80\x89注意:使用重载运算符会导致函数调用;上述\n仅涵盖具有内置含义的运算符。\xe2\x80\x89\xe2\x80\x94\xe2\x80\x89end note\xe2\x80\x89] 如果表达式是此可选转换后的纯右值,则应用临时具体化转换。[\xe2\x80\x89注意:如果表达式是类类型的左值,则它必须具有易失性复制构造函数来初始化作为左值到右值转换的结果对象的临时对象。\xe2\x80\x89\xe2\x80\x94\xe2\x80\x89end note\xe2\x80\x89] 对泛左值表达式进行求值,并丢弃其值。
\n
在非易失性情况下,没有左值到右值的转换。因此我们可以放心地说该变量没有被访问。
\n\n然而,在易变的情况下,您在强制转换表达式内部有间接寻址,并且会经历左值到右值的转换。因此,易失性被读取,并且您通过读取未初始化的对象得到未定义的行为。
\n\n为了避免围绕易失性左值的未定义行为,可以将相关变量注释为[[maybe_unused]]. 这是经过批准的方式,也是我在非易失性情况下比强制转换更喜欢的方式。