8

给定以下课程:

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

  private:
    volatile int value_;
};

value() 成员函数是否也必须标记为 volatile 以避免被优化,或者它是否可以编写?谢谢。

4

4 回答 4

7

它与工作方式完全相似const

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

所以...

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

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

但是,请记住这与多线程无关volatile,它不会帮助您编写线程安全的代码。对于与并发相关的任何事情,它都是错误的工具。

于 2012-05-01T13:54:22.743 回答
4

value() 成员函数是否也必须标记为 volatile 以避免被优化,或者它是否可以编写?

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

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

听起来您想要了解原子变量。看看std::atomic。

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

于 2012-05-01T13:56:38.157 回答
4

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

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

[*] 一些编译器(即 gcc)具有特殊的属性,您可以使用这些属性告诉它一个函数是函数(即它没有副作用,并且输出仅取决于提供的参数)以允许对一个函数进行多次调用优化了,例如在这个循环中:

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

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

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

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

于 2012-05-01T14:19:42.850 回答
2

常量和易失性成员函数(仅限 C++)

可以为常量和非常量对象调用使用 const 限定符声明的成员函数。非常量成员函数只能为非常量对象调用。类似地,可以为 volatile 和 nonvolatile 对象调用使用 volatile 限定符声明的成员函数。只能为非易失性对象调用非易失性成员函数。

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

于 2012-05-01T13:49:56.673 回答