简体   繁体   中英

Volatile Member Functions (C++)

Given the following class:

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

  private:
    volatile int value_;
};

Does the value() member function also have to be marked as volatile to avoid getting optimized away or is it okay as written? Thanks.

It is completely analogous to how const works.

If you have a const object, only member functions marked const are callable.

And so...

If you have a volatile object, only member functions marked volatile are callable.

As long as the object itself is not volatile , it makes no difference whether the function is.

However, do keep in mind that volatile has nothing to do with multithreading, and it will not help you write thread-safe code. It is the wrong tool for anything concurrency-related.

Does the value() member function also have to be marked as volatile to avoid getting optimized away or is it okay as written?

Marking the member function volatile will have no effect on whether it is optimized away or not. It is fine as written.

The worry is if I have MyClass c; and then call c.value(); a couple times, the compiler might think c.value() will return the same value (even though it could have possibly changed..)

It sounds like what you want is to learn about atomic variables. Take a look at std::atomic.

If you really want to learn about volatile, read this paper: http://www.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf

The worry is if I have MyClass c; and then call c.value(); a couple times, the compiler might think c.value() will return the same value (even though it could have possibly changed..)

In a separate compilation model, where the compiler does not see the internals of the function, it cannot assume that they will not have side effects ([*]), and thus cannot remove the different calls to the function. If the compiler is seeing the definition of the function and inlining the code, then it sees that the member is volatile and thus cannot optimize it away either.

[*] Some compilers (namely gcc) have special attributes that you can use to tell it that a function is pure (ie it has no side effects and the output depends only on the arguments provided) to enable multiple calls to a function to be optimized away, for example in this loop:

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

Because strlen is marked as pure in the library, the compiler will cache the value and transform the loop into:

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

But the library must tell the compiler specifically that this can be done. Without the extra information in the shape of attributes, nothing can be assumed and the strlen function would have to be called in each iteration of the loop.

Constant and volatile member functions (C++ only)

A member function declared with the const qualifier can be called for constant and nonconstant objects. A nonconstant member function can only be called for a nonconstant object. Similarly, a member function declared with the volatile qualifier can be called for volatile and nonvolatile objects. A nonvolatile member function can only be called for a nonvolatile object.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM