易失性成员函数(C ++)

时间:2012-05-01 13:45:39

标签: c++ multithreading volatile

鉴于以下课程:

class MyClass {
  public:
    int value() const {
      return value_;
    }

  private:
    volatile int value_;
};

还是必须将value()成员函数标记为volatile以避免被优化掉或者写得好吗?感谢。

4 个答案:

答案 0 :(得分:7)

这完全类似于const的工作方式。

如果您有const个对象,则只有标记为const的成员函数才可以调用。

所以......

如果您有volatile个对象,则只有标记为volatile的成员函数才可以调用。

只要对象本身不是volatile,函数是否正常就没有区别。

但是,请记住,volatile 没有与多线程有关,并且可帮助您编写线程安全的代码。对于任何与并发相关的东西,它都是错误的工具。

答案 1 :(得分:4)

  

是否还必须将value()成员函数标记为volatile以避免被优化掉或者写得好吗?

将成员函数标记为volatile将不会影响它是否被优化。写得很好。

  

担心的是我是否有MyClass c;然后调用c.value();有几次,编译器可能会认为c.value()将返回相同的值(即使它可能已经改变了..)

听起来你想要的是了解原子变量。看一下std :: atomic。

如果您真的想了解volatile,请阅读本文:http://www.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf

答案 2 :(得分:4)

  

担心的是我是否有MyClass c;然后调用c.value();有几次,编译器可能会认为c.value()将返回相同的值(即使它可能已经改变了..)

在单独的编译模型中,编译器没有看到函数的内部,它不能假设它们不会有副作用([*]),因此无法删除对函数的不同调用。如果编译器看到函数的定义并内联代码,那么看到成员是volatile,因此也无法优化它。

[*]有些编译器(即gcc)有一些特殊的属性可以用来告诉它一个函数是 pure (即它没有副作用,输出只依赖于提供的参数)启用对要优化的函数的多个调用,例如在此循环中:

const char* lit = "Literal";
int sum = 0;
for ( int i = 0; i < strlen(lit); ++i ) {
    sum += lit[i];
}

因为strlen在库中标记为纯,所以编译器将缓存该值并将循环转换为:

const char* lit = "Literal";
int sum = 0;
int __len = strlen(lit);
for ( int i = 0; i < __len; ++i ) {
    sum += lit[i];
}

但是库必须具体告诉编译器可以做到这一点。如果没有属性形式的额外信息,则不能假设任何内容,并且必须在循环的每次迭代中调用strlen函数。

答案 3 :(得分:2)

  

常量和volatile成员函数(仅限C ++)

     

可以调用使用const限定符声明的成员函数   常量和非常量对象。非常数成员函数可以   仅为非常量对象调用。同样,一个成员函数   用volatile限定符声明可以调用volatile和   非易失性物体。只能调用非易失性成员函数   对于非易失性物体。

http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr028.htm

相关问题