Oli*_*liv 11 c++ volatile language-lawyer
考虑以下这段代码:
struct S{
int i;
S(int);
S(const volatile S&);
};
struct S_bad{
int i;
};
volatile S as{0};
volatile S_bad as_bad{0};
volatile int ai{0};
void test(){
ai; //(1)=> a load is always performed
as; //(2)=> Should call the volatile copy constructor
as_bad; //(3)=> Should be ill-formed
}
Run Code Online (Sandbox Code Playgroud)
表达式ai;,as;并且as_bad是废弃的值表达式,并根据C++草案标准N4659/[expr] .12我预计在这三种情况下将应用左值到右值.对于情况(2),这应该导致对volatile复制构造函数(S(const volatile S&))[expr]/12的调用
[...]如果表达式是此可选转换后的prvalue,则应用临时实现转换([conv.rval]).[注意:如果表达式是类类型的左值,则它必须具有易失性复制构造函数来初始化临时值,该临时值是左值到右值转换的结果对象. - 结束说明]
因此案例(3)应该是不正确的.
然而,编译器的行为似乎很混乱:
GCC:
ai;=>加载值ai;as; =>没有代码生成,没有警告;as_bad;=>加载as_bad.i.Clang不会为case(2)生成负载并生成警告:表达结果未使用; 分配给变量以强制挥发性负载[-Wunused-volatile-lvalue]
ai;=>加载值ai;as;=>没有生成代码; 警告表达结果未使用; 分配给变量以强制挥发性负载[-Wunused-volatile-lvalue]as_bad;=>相同as;.MSVC在两种情况下都执行加载.
ai;=>加载值ai;as;=> loads as.i(不调用volatile复制构造函数)as_bad;=>加载as_bad.i.根据标准我的预期总结:
ai;=>加载值ai;as;=> S(const volatile S&)以as参数调用;as_bad; =>生成编译错误我对标准的解释是对的吗?哪个编译器是正确的?
b ? (x,y) : z不计算 if 的y情况)并添加有关易失性复制构造函数的注释。所以我的结论是(从 C++11 开始)你是正确的,所有编译器都是错误的。特别是,S::i除非您的复制构造函数读取它,否则不应发生加载。当然,“访问”的实现定义性质与格式良好的问题无关;它只影响是否ai真正生成加载指令。存在聚合的问题S_bad,但这无关紧要,因为它没有被列表初始化。
| 归档时间: |
|
| 查看次数: |
307 次 |
| 最近记录: |