2016-02-08 55 views
9

如问题: 比方说,我有一个小小的一段代码是这样的:C++挥发物,挥发性成员

#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; 
    } 

调用构造函数。

如果我尝试使用代码内部的变量(即,cout << foo.a << endl;),则在两种情况下程序集输出都是等效的。

难道我得到以下权利,即:

在第一种情况下,有对结构没有任何访问,所以它得到完全优化掉。

在第二个中,struct的字段被指示为在构造期间也可能改变的字段,并且因此foo()被调用,不管是什么。

补充: 我试着上面的代码摆弄: 像while(foo.a--);作品调用的东西如预期,但实际发生的,而不是删除/优化过程中的结果所取代,因此看来挥发性实际上是继承的,但ctor在这种奇怪的行为(或者至少在第一次意外)中行事。

编辑号2:

我铿锵和MSVC检查,它的行为同样的方式在海湾合作委员会。

+0

看起来像一个bug给我。 “** [basic.type.qualifier] /(1.2)** A * volatile *对象是类型为'volatile T'的对象,这种对象的子对象...”因此,在这两个示例中,都是'foo。 a'是一个易变的对象,对它的操作是可观察的副作用,不应该被优化掉。 –

+0

@IgorTandetnik我从来没有真正理解如何易变的自动变量可观察。接受它是一个编译器错误,很难看出它在实践中如何破坏任何东西(并且很难看出编译器应该如何处理这种可能性,优化器*应该*能够优化用于'foo ''的构造函数,而不必针对'foo'被实例化为volatile的情况分别进行优化。) –

回答

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计算器/ dtors不能用volatile关键字标记(如Defining volatile class object),所以你必须稍微改变你的代码(也许调用ctor中的volatile成员函数会做这件事,但这只是一个猜测)。

+0

Ctor不能被v指定。这里似乎就是这种情况,尽管我希望以更明确的方式看到它通过标准解释,就是这样。我已经添加了一些信息的问题顺便说一句。 – alagner

+0

是的,我想我写道:“AFAIK ctors/dtors不能用volatile关键字标记”。或者你是指别的? –