考虑以下语句

volatile int a = 7;
a;   // statement A
volatile int* b = &a;
*b;  // statement B
volatile int& c = a;
c;   // statement C

现在,我一直试图在标准中找到一个要点,告诉我编译器在遇到这些语句时的行为。我所能找到的就是A(可能还有C)给了我一个左值,B也给了我:

“§5.1.1.8主表达式-常规”说



“第5.3.1节一元运算符”说



lang和海湾合作委员会

我在clang++ 3.2-11和g++ 4.7.3中进行了尝试,第一个在C++ 11模式下产生了三个读取,在C++ 03模式下产生了零读取(输出三个警告),而g++仅产生了前两个,显式警告我认为第三个不会生成。



很明显,从表达式中的标准表达式中引出的是哪种类型的值,但是:
哪一个语句(A,B,C)应该根据C++标准从 volatile 实体中读取数据?

最佳答案

关于“隐式取消引用”的G++警告来自gcc/cp/cvt.c中的代码,该代码有意不通过引用加载值:

    /* Don't load the value if this is an implicit dereference, or if
       the type needs to be handled by ctors/dtors.  */
    else if (is_volatile && is_reference)

G++故意这样做,因为如手册(When is a Volatile C++ Object Accessed?)所述,该标准尚不清楚由什么构成对volatile限定对象的访问。如前所述,您需要强制从左值到右值的转换以从 volatile 中加载负载。

Clang在C++ 03模式下发出警告,表示类似的解释:
a.cc:4:3: warning: expression result unused; assign into a variable to force a volatile load [-Wunused-volatile-lvalue]
  a;   // statement A
  ^
a.cc:6:3: warning: expression result unused; assign into a variable to force a volatile load [-Wunused-volatile-lvalue]
  *b;  // statement B
  ^~
a.cc:8:3: warning: expression result unused; assign into a variable to force a volatile load [-Wunused-volatile-lvalue]
  c;   // statement C
  ^
3 warnings generated.

G++行为和GCC手册对于C++ 03似乎是正确的,但是DR 1054引入了C++ 11与C++ 03的区别(这也解释了为什么Clang在C++中表现不同)3和C++ 11模式)。 5 [expr] p10定义了一个废弃值表达式,并说对于volatile,左值到右值转换应用于id表达式,例如语句A和C。左值到右值转换的规范(4.1 [conv.lval])表示结果是glvalue的值,它构成了对volatile的访问。根据5p10,您的所有三个语句都应该是访问权限,因此G++对语句C的处理需要更新以符合C++ 11。我已将其报告为http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59314

07-24 09:45
查看更多