C++ volatile member functions
Marking a member function volatile
is like marking it const
; it means that the receiver object is treated as though it were declared as a volatile T*
. Consequentially, any reference to x
or y
will be treated as a volatile
read in the member function. Moreover, a volatile
object can only call volatile
member functions.
That said, you may want to mark x
and y
volatile
anyway if you really do want all accesses to them to be treated as volatile
.
What does it mean when a member function is volatile?
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
}
Calling volatile member function using not volatile object in C++
The rule is same as const
member function. A volatile
member function could be called on a non-volatile
object, but a non-volatile
member function couldn't be called on a volatile
object.
For your case, A::func()
will be invoked fine. If you make them opposite, the compilation would fail.
class A
{
private:
int x;
public:
void func(int a) // non-volatile member function
{
x = a;
cout<<x<<endl;
}
};
int main()
{
volatile A a1; // volatile object
a1.func(10); // fail
return 0;
}
Volatile function
In your code, the volatile
keyword does not apply to the function, but to the return type, it is the equivalent of:
typedef volatile int Type;
Type foo();
Now, in C++ you can make a member function volatile
, in the same way that the const
qualifier, and the behavior is the same:
struct test {
void vfunction() volatile;
};
Basically you cannot call a non-volatile (alterantively non-const) function on a volatile (const respectively) instance of the type:
struct test {
void vfunction() volatile;
void function();
};
volatile test t;
t.vfunction(); // ok
t.function(); // error
Member functions that are volatile and const
If this
is marked volatile
, it will affect the compiler's ability to optimise away updates to/from the members pointed to by *this
.
The TYPICAL use-case for volatile
is where you have hardware registers - not particularly typical to use a class
to describe hardware registers, but we can do it.
For example, one could have a class like this:
class my_hardware_device
{
public:
int32_t reg1;
int32_t reg2;
private:
int32_t reserved;
public:
int32_t reg4;
int func() volatile;
};
volatile my_hardware_device hw1 =
reinterpret_cast<volatile my_hardware_device*>(0x10000000);
...
int my_hardware_device::func() volatile
{
reg2 = 3;
reg3 = 8;
reg2 = 7;
if (reg2 == 4)
{
...
}
}
...
hw1->func();
Without volatile
, the compiler could very well decide to remove the reg2 = 3
and determine that reg2 == 4
is always false, both because of reg2 = 7;
. But since it's actually pointing at some hardware, it doesn't behave the way the compiler would expect. [This is a very silly example just constructed to show how it could work - I'm not by any means suggesting that this is a "correct" or "good" solution for any such hardware interface - never mind portability problems, and all manner of other things - and of course the vtable would cause complete havoc if you ever tried to use this with virtual functions - and if you are dealing with hardware in a driver, you probably do want vtables to solve hardware variants, giving yet another reason for implementing this sort of code in a different way.]
The const
variant means that the compiler is not allowed to write to members of *this
(in other words members in the class foo
in your example), except if they are marked as mutable
(or if a const_cast
is used to cast away the constness - const_cast
can also be used to cast away volatileness, by the way).
Combining the both const
and volatile
simply means that reads can not be optimised away, and the compiler is not allowed to update the members of *this
.
c++: volatile member function in volatile instance - assigning array to pointer is invalid conversion?
Volatility and constness do not propagate through pointers, but they do propagate through arrays. So in a volatile instance of the class, firstElementPt
is itself volatile, but the thing it points to is not. The intArray
elements however are volatile. You are attempting to point a volatile-pointer-to-a-non-volatile-int to a volatile int
. This is not allowed.
C++ - What does volatile represent when applied to a method?
It is a volatile member which, just like a const member can only be called on const objects, can only be called on volatile objects.
What's the use? Well, globally volatile is of little use (it is often misunderstood to be applicable for multi-threaded -- MT -- programming, it isn't the case in C++, see for instance http://www.drdobbs.com/high-performance-computing/212701484), and volatile class objects are even less useful.
IIRC A. Alexandrescu has proposed to use the type checking done on volatile objects to statically ensure some properties usefull for MT programming (say that a lock has been taken before calling a member function). Sadly, I don't find the article back. (Here it is: http://www.drdobbs.com/184403766)
Edit: added links from the comments (they where added also in the question).
Volatile Member Functions (C++)
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
Related Topics
How to Use Threads to Speed Up File Reading
Simple Ipc Between C++ and Python (Cross Platform)
C++ Overloaded Virtual Function Warning by Clang
How to Use C++ Std::Ostream with Printf-Like Formatting
Counting the Number of Lines in a Text File
Gsl::Not_Null<T*> VS. Std::Reference_Wrapper<T> VS. T&
How to Write the Following as a C++ MACro
Opencv: How to Visualize a Depth Image
Calling Derived Class Function from Base Class
Is There a C++11 Syntax File for Vim
Operator << Must Take Exactly One Argument
Why Not Just Use Random_Device
What's the Best Way to Check If a File Exists in C++? (Cross Platform)
Sqlite3_Exec() Callback Function Clarification
Reinterpret_Cast Between Char* and Std::Uint8_T* - Safe