C ++易失性对象,非易失性成员

时间:2016-02-08 00:58:25

标签: c++ volatile

如问题所示: 让我们说我有一小段这样的代码:

1, 2, 3

使用 #include <iostream> using namespace std; struct foo { int a; foo() : a(12) {}; }; int main() { volatile foo x; return 0; } 编译,结果证明g++ -g -O2初始化已经过优化。

然而那个:

x

调用构造函数。

如果我尝试使用代码中的变量(即 #include <iostream> using namespace std; struct foo { volatile int a; foo() : a(12) {}; }; int main() { volatile foo x; return 0; } ),则两种情况下的汇编输出都是等效的。

我是否有以下权利:

在第一种情况下,根本无法访问结构,因此它会完全被优化。

在第二个中,struct的字段被指示为在构造期间也可以改变的字段,因此无论如何都会调用foo()。

添加了: 我试过摆弄上面的代码: 调用cout << foo.a << endl;之类的东西按预期工作,它实际上发生而不是在优化期间被结果删除/替换,因此看起来volatile实际上是继承的,但ctor在这种奇怪的行为(或者至少在开始时是意外的)方式。

编辑编号2:

我用clang和MSVC检查它,它的行为与gcc相同。

1 个答案:

答案 0 :(得分:2)

我的理解如下(我不确定):

在C ++ volatile关键字中强制编译器不要优化看似冗余的加载和存储到内存,即如果你有这样的示例代码:

int x = 5;
x = 6;

不会更改为:

int x = 6;

这是因为x可能指向内存中的某个地址,这是其他人读取的,而您实际上并未在程序中读取它(想象您通过USART发送了一些配置微控制器通过写入某个存储器地址,并且微控制器从该地址读取它的配置 - 如果编译器要优化对该存储器的写入,则整个程序会发生故障。

必须记住的另一件事是,当一个类的实例用volatile说明符声明时,它的成员继承这个说明符(正如Igor Tandetnik在评论中指出的,指的是C ++标准)。但这不是全部真相,因为为了获得volatile行为,您必须调用标记为volatile的成员函数 - 类似于将成员函数标记为const(请看这个:http://www.devx.com/tips/Tip/13671)。因为AFAIK ctors / dtors不能用volatile关键字标记(如在Defining volatile class object中),所以你必须稍微改变你的代码(也许从ctor中调用volatile成员函数会做的事情,但是这个只是一个猜测。)