views:

850

answers:

5

I was reading about volatile member function and came across an affirmation that member function can be both const and volatile together. I didn't get the real use of such a thing. Can anyone please share their experience on practical usage of having member function as const and volatile together.

I wrote small class to test the same:

class Temp
{
public:

    Temp(int x) : X(x)
    {
    }

    int getX() const volatile
    {
     return X;
    }

    int getBiggerX()
    {
     return X + 10;
    }
private:
    int X;
};

void test( const volatile Temp& aTemp)
{
    int x = aTemp.getX();
}

int main(int argc, char* argv[])
{
    const volatile Temp aTemp(10);
    test(aTemp);

    return 0;
}
+1  A: 

I've never needed anything being both const and volatile, but here's my guess:

Const: You, your code, is not allowed to change the value.

Volatile: The value may change over time without your program doing anything.

So some read-only data exposed by another process or by some hardware would be const and volatile. It could even be memory-mapped into your process and the page marked read-only, so you'd get an access violation if you tried to write to it if it wasn't const.

jalf
+13  A: 

The cv qualification distilled means:

I won't change the value, but there is something out there that can.

You are making a promise to yourself that you won't change the value (const qualification) and requesting the compiler to keep its slimy hands off of this object and turn off all optimization (volatile qualification). Unfortunately, there is little standard among the compiler vendors when it comes to treating volatile fairly. And volatile is a hint to the compiler after all.

A practical use case of this is a system clock. Supposing 0xDEADBEEF was your system specific address of a hardware clock register you'd write:

int const volatile *c = reinterpret_cast<int *>(0xDEADBEEF);

You can't modify that register value, but each time you read it, it is likely to have a different value.

Also, can use this to model UARTs.

dirkgently
add to "... something out there that can.", and I always want to read the value from memory not CPU register or a cache.
Pop Catalin
I was already editing my post seeing as it was a little too short.
dirkgently
As an embedded guy, I use pointers to const volatile all the time (just like your example.) But I think the OP wanted an example of when it would apply to a member function, not a pointer.
Dan
If you can use it for a variable, you can extend it to a function. I assumed that to be natural.
dirkgently
+8  A: 

You asked for a practical example of volatile member functions. Well i can't think of one because the only situations i could imagine are so low-level that i would not consider using a member function in the first place, but just a plain struct with data-members accessed by a volatile reference.

However, let's put a const volatile function into it just for the sake of answering the question. Assume you have a port with address 0x378h that contains 2 integers, 4 bytes each. Then you could write

struct ints {
    int first;
    int second;
    int getfirst() const volatile {
        return first;
    }

    int getsecond() const volatile {
        return second;
    }
      // note that you could also overload on volatile-ness, just like
      // with const-ness
};

// could also be mapped by the linker. 
ints const volatile &p = *reinterpret_cast<ints*>(0x378L);

You are stating

I'm not changing them, but another thing outside this abstract semantics could change it. So always do a real load from its address.

Actually, volatile signals that the value of an object might not be the value last stored into it but is actually unknown and might have been changed in between by external (not observable by the compiler) conditions. So when you read from a volatile object, the compiler has to emulate the exact abstract semantics, and perform no optimizations:

a = 4;
a *= 2; 
  // can't be optimized to a = 8; if a is volatile because the abstract
  // semantics described by the language contain two assignments and one load.

The following already determines what volatile does. Everything can be found in 1.9 of the Standard. The parameters it talks about are implementation defined things, like the sizeof of some type.

The semantic descriptions in this International Standard define a parameterized nondeterministic abstract machine. This International Standard places no requirement on the structure of conforming implementations. In particular, they need not copy or emulate the structure of the abstract machine. Rather, conforming implementations are required to emulate (only) the observable behavior of the abstract machine as explained below. [...]

A conforming implementation executing a well-formed program shall produce the same observable behavior as one of the possible execution sequences of the corresponding instance of the abstract machine with the same program and the same input. [...]

The observable behavior of the abstract machine is its sequence of reads and writes to volatile data and calls to library I/O functions.

Johannes Schaub - litb
Thanks for the examples :-)
aJ
+1  A: 

I think that the reason we have "const volatile" functions is the same as the reason we have "protected" inheritance: The grammar allows it , so we had better think up a meaning for it.

anon
Protected inheritance was a mistake. "const volatile" has a perfectly good meaning - the code won't change the value, but something else might.
David Thornley
I meant (obvious I would have thought from the context) "const colatile" member functions.
anon
Ah, I was looking at the code. Still, what's the problem with "const volatile" member functions? I'm not sure there's many uses for volatile member functions, but if so there's no reason they shouldn't also be const.
David Thornley
protected inheritence is/was not a mistake. it's just a mistake to use it for the wrong thing.
Johannes Schaub - litb
and he asked about member functions. i'm not sure why so many people actually come up with volatile variables as answers and comments :) so far neil and mine seem the only answers actually answering his question.
Johannes Schaub - litb
we will have to differ on protected inheritance - but let's not get into that here
anon
neil, hehe yeah better not :)
Johannes Schaub - litb
A: 

One situation I can think of that could require both const and volatile on a member function would be in an embedded systems situation where you had a the function was logically const but actually had to modify a data cache in a shared memory location (e.g. building a bitmap on demand and caching the bitmap in case the same bitmap was needed again soon). It certainly does not come up very often.

Bruce Ikin