10

I normally see the const specifier used to indicate a const member function. But what does it mean when the volatile keyword is used?

void f() volatile {}

This compiles fine for me but I don't understand what this is for. I couldn't find any information about this in my search so any help is appreciated.

Update: To make it clear, I know what volatile is for. I just don't know what it means in this context.

David G
  • 94,763
  • 41
  • 167
  • 253

3 Answers3

15

The volatile qualifier on a member function is analogous to the const qualifier. It allows the member function to be called on volatile objects:

struct A {
    void f() volatile {}
    void g() {}
};

int main() {
    A volatile a;
    a.f(); // Allowed
    a.g(); // Doesn't compile
}
Mankarse
  • 39,818
  • 11
  • 97
  • 141
  • 2
    what does volatile object means? [can change?] – Dineshkumar May 25 '13 at 03:33
  • 2
    `volatile` indicates that the value may be accessed by things that are unknown to the compiler (such as memory mapped hardware) and disables certain optimisations. Accessing a `volatile` value is treated as a side-effect for the purposes of the as-if rule. – Mankarse May 25 '13 at 03:36
  • But aren't objects "by definition" volatile for member functions, if we think about a member function as getting an `A* this` implicit parameter? – einpoklum Jan 05 '17 at 21:43
  • @einpoklum I don't follow your logic. `A* this` is not cv qualified; so why would it be a pointer to volatile "by definition"? – Mankarse Jan 05 '17 at 23:47
  • Because you don't know what a pointer points to. It might point to a volatile variable. You can't assume that it doesn't. – einpoklum Jan 06 '17 at 00:21
  • @einpoklum: You do know what it points to. If `A` is not volatile-qualified, then the pointer can't point to a volatile variable. (It is disallowed by the type-system, and if you use `const_cast` to bypass this, you hit undefined behavior). The type system will only allow it if you qualify the member function with `volatile`. It works in the same way for `const` too. – Mankarse Jan 06 '17 at 02:35
10

On a member function, const and volatile qualifiers apply to *this. Accesses of any instance members within that member function would then be volatile accesses, with the same semantics as any volatile variable. In particular, non-volatile member functions cannot be called on a volatile object, and volatile applies to overloading in the same way as const:

#include <iostream>

class C {
public:

    void f() {
        std::cout << "f()\n";
    }

    void f() const {
        std::cout << "f() const\n";
    }

    void f() volatile {
        std::cout << "f() volatile\n";
    }

    void f() const volatile {
        std::cout << "f() const volatile\n";
    }

};

int main() {

    C c1;
    c1.f();

    const C c2;
    c2.f();

    volatile C c3;
    c3.f();

    const volatile C c4;
    c4.f();

}
Jon Purdy
  • 53,300
  • 8
  • 96
  • 166
  • compiler shows error uninitialized const for c2 and c4? – Dineshkumar May 25 '13 at 04:13
  • @Dineshkumar: It shouldn’t. What compiler are you using? – Jon Purdy May 25 '13 at 04:38
  • @Dineshkumar: What version? On [ideone](http://ideone.com/), I can reproduce your error with GCC 4.3.2 but not 4.7.2, so I think that’s a compiler bug. The object is initialised by the implicit default constructor. – Jon Purdy May 25 '13 at 04:43
  • when i added a constructor it works fine. why is it so? – Dineshkumar May 25 '13 at 04:45
  • 2
    @Dineshkumar: It was actually [an error in the standard](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#253) which was fixed in C++11 and changed accordingly in GCC 4.6. – Jon Purdy May 25 '13 at 05:05
  • `this` is a pointer. What does it mean for it to be volatile? By definition, compilers assume that whatever is pointed to by a pointer is subject to changes the compiler is not tracking. Unless it's `__restrict__`ed... – einpoklum Jan 05 '17 at 21:44
  • @einpoklum: The pointed-to type is cv-qualified, not the pointer type. So in a `volatile` member function, `this` has type `volatile T*` = `T volatile*`, just as in a `const` member function, `this` has type `const T*` = `T const*`. That means *dereferencing* `this` is a volatile access, but simply accessing the `this` pointer itself is not—that is, it’s not `T* volatile`. – Jon Purdy Jan 05 '17 at 22:11
2

Objects declared as volatile are not used in certain optimizations because their values can change at any time. The system always reads the current value of a volatile object at the point it is requested, even if a previous instruction asked for a value from the same object. Also, the value of the object is written immediately on assignment.

A volatile object can only call volatile member functions.

So by marking the member function as volatile you'd be making any access to the non-static data members of the object within that member function as volatile.

TelKitty
  • 3,146
  • 3
  • 18
  • 21