If you have a class member function marked volatile, is it possible to cast away volatile on a class member when it's bein used within that function?
Yes. To cast away the volatile-ness of an object, const_cast is used:
T & t = const_cast<T&>(volatile_t);
This is the way. But whether you should use it in your code or not, I cannot say without looking at the code. In general, casting away the const-ness as well as volatile-ness, is a dangerous idea, and should be done only after very careful examination of all cases.
You can cast away volatile from any context by using const_cast. You are asking precisely about casting away inside a volatile member, but that does not make any difference.
The volatile in the function is a check that tells the compiler not to complain if you try to call that method on a volatile object (or through a reference or pointer to volatile object), which is unrelated to the volatile-ness of the members.
What I am trying to say is that if you expect the behavior while accessing data members to be consistent with volatile semantics just because the code is inside a volatile member method, that won't happen.
Related
It seems like the volatile comparison functions in shared_ptr implementation do not exist.
Does it even make sense to exist?
Essentially no, the standard doesn't cater for comparisons or boolean conversion on a volatile shared_ptr.
The following fails to compile...
auto main() -> int {
volatile shared_ptr<int> a;
if (a == nullptr) // fails
; // empty
if (a) // fails
; // empty
}
You could cast the volatile off (via. a const_cast), but I'm not sure that will have the desired outcome. From the cppreference:
Modifying a const object through a non-const access path and referring to a volatile object through a non-volatile glvalue result in undefined behavior.
In more general terms, in not marking member methods as volatile, the class or library implementors are effectively saying "this is not intended to be use as a volatile object" - if it were, then the appropriate methods or overloads would provide for volatile objects. Similarly, this applies to const, in marking members as const, they are saying "this class can be used as a const object.
Why is the volatile needed, what external sources could be modifying the shared_ptr "without the knowledge of the compiler" (this is one of the uses of volatile)? If there are threading issues, then you would be better served with one the thread library utilities, or if the requirement is simply turning off optimisations, various compilers have mechanisms for this already (pragmas etc.).
Volatile is just an indication to the compiler that the memory may change unexpectedly. Turns off some optimizations. Under the covers its just a memory address.
The shared pointer is just holding/managing the resource. That said, since std::shared_ptr::get() isn't marked volatile, you cannot really use a shared_ptr to manage a volatile pointer in a accessible way.
I'd recommend using a naked pointer, and using scoped exit or the destructer to clean up after it.
If you are using volatile because the pointer may be modified by another thread, you may want to consider using std::atomic instead of volatile. In threading workflows, before std::atomic, pointers that were accessed from other threads were usually marked volatile. That is no longer best practice.
A lot of people are saying
"volatile member function is completely analogous to how const works."
They are quite similar in the sense of if a pointer is marked as const/volatile, it can only access member functions marked as const/volatile.
But actually defining a member function as const has an additional effect, which makes the function read-only. Any modifications of the object inside the function will cause a compiler error. Is there such analogs in volatile member function?
Well, a volatile member function will make the object members volatile, that is, this will be as if it were defined volatile T * const this. And as a consequence, any reference to a member variable is also volatile.
Remember that volatile read/writes are operations that cannot be elided/reordered by the compiler. They are usually used to implement memory-mapped hardware devices or things like that.
Frankly speaking I've never been a use of this feature, other than doing smart tricks to filter the access to the function, not to make use of the volatile-ness of the object. If your code is low level enough to need volatile you probably will want to go putting the volatile just in the variables you need.
Short answer: yes.
If an instance of an object is declared volatile then it is an error to call non-volatile methods on it (or for those methods to call other non-volatile methods).
A non-volatile instance can still call volatile methods, but not that it is perfectly legal to have two otherwise identical methods in a class - one volatile and one not. In that case a non-volatile instance will call the non-volatile version of the method.
But actually defining a member function as const has an additional effect, which makes the function read-only.
That's a bit of a misconception. It doesn't make the member function read-only - it makes *this const. There's a small, but important, difference between the two (the member function can still modify mutable members, and if it wants to be nasty, it can cast away the const-ness of *this to modify anything it wants, and the compiler won't complain).
And a volatile member function works in the exact same way - it makes *this volatile.
I have a back up copy of data that I would like to protect so I made it const. I need to violate that constness on two occassions, once to store virgin data to it:
fgBlocks.CopyInto((BlkArray&)backUpCopy);
w.r.t.
result CopyInto(BlkArray &replica) const {/**/}
and again when I call RemoveAll() on it which is a non-const method:
((BlkArray)backUpCopy).RemoveAll(true);
Is the first cast (shown above, (BlkArray&)) correct? It's the one aspect of indirection I haven't cast to before now. Then again I'll add another unused aspect, that of casting away constness for calling an object's methods, which the compiler isn't accepting as shown above.
The members are declared like this:
BlkArray fgBlocks;
const BlkArray backUpCopy;
I'm trying to extend Correa's solution so have:
BlkArray *pBUCopy = (BlkArray *)&backUpCopy;
fgBlocks.CopyInto(*pBUCopy);
Only problem now is the compiler is failing due to
uninitialized member 'MyClass::backUpCopy' with 'const' type 'const BlockArray'
Be aware that if you do this and the object really is const, then modifying it after casting away the constness is undefined behaviour.
fgBlocks.CopyInto(const_cast<BlkArray&>(backUpCopy));
Same thing for the other one:
const_cast<BlkArray&>(backUpCopy).RemoveAll(true);
You can circumvent this problem by simply marking all methods as const, except RemoveAll and CopyFrom, the latter being made to be a method of BlkArray that either implements the logic or passes *this to CopyInto.
To be more secure about who can clear the data / copy new stuff into it, you may make those methods private and declare the necessary classes as friends, or use the passkey pattern to protect those two methods.
There is a little trick I learned looking at Qt's internals:
MyClass:circunventConst() const
{
MyClass* that = const_cast<MyClass*>(this);
that->myProtectedVariable = value;
}
Why can't a volatile object call a non-volatile member function?
In case of const, it makes sense that calling a non-const member function violates the constness of the the object and hence it is prohibited. But why in the case of volatile?
In case of const, it makes sense that calling a non-const member function violates the const-ness of the the object and hence it is prohibited. But why in the case of volatile?
It's just the same for volatile. Volatile means every access to an object is a visible side effect and cannot be eliminated. If you called a nonvolatile method on a volatile object, you would violate this property (because the nonvolatile method would treat the object just as a normal object). Therefore, it is impossible.
From the standard:
7.1.5.1. If an attempt is made to refer to an object defined with a volatile-quailified type through the use of an lvalue with a
non-volatile-quailified type, the program behaviour is undefined.
I'm guessing your compiler posts an error to prevent undefined behavior. The standard stating so should be reason enough.
The volatile qualifier works much in the same way as const works. To see what can be done thanks to this, take a look at this Alexandrescu article.
That article should also give you some insight into the why.
AFAIK we cannot change a value of a constant variable in C.
But i faced this interview question as below:
In C++, we have procedure to change the value of a constant variable.
Could anybody tell me how could we do it?
You can modify mutable data members of a const-qualified class-type object:
struct awesome_struct {
awesome_struct() : x(0) { }
mutable int x;
};
int main() {
const awesome_struct a;
a.x = 42;
}
The behavior here is well-defined.
Under the circumstances, I think I'd have explained the situation: attempting to change the value of a variable that's const gives undefined behavior. What he's probably asking about is how to change a variable that isn't itself const, but to which you've received a pointer or reference to const. In this case, when you're sure the variable itself is not const-qualified, you can cast away the const-ness with const_cast, and proceed to modify.
If you do the same when the variable itself is const-qualified the compiler will allow the code to compile, but the result will be undefined behavior. The attempt at modifying the variable might succeed -- or it might throw an exception, abort the program, re-format your NAS appliance's hard drives, or pretty much anything else.
It's probably also worth mentioning that when/if a variable is likely to need to be used this way, you can specify that the variable itself is mutable. This basically means that the variable in question is never const qualified, even if the object of which it's a part is const qualified.
There is no perfect way to cast away const-ness of a variable(which is const by definition) without invoking UB
Most probably the interviewers have no idea what they are talking about. ;-)
You cannot change the value of a constant variable. Trying to do so by cheating the compiler, invokes undefined behavior. The compiler may not be smart enough to tell you what you're doing is illegal, though!
Or maybe, you mean this:
const char *ptr= "Nawaz";
ptr = "Sarfaraz";
??
If so, then it's changing the value of the pointer itself, which is not constant, rather the data ptr points to is constant, and you cannot change that for example by writing ptr[2]='W';.
The interviewer was looking for const_cast. As an added bonus, you can explain scenarios where const_cast make sense, such as const_cast<MyClass *>(this)->doSomething() (which can be perfectly valid, although IMO not very clean), and scenarios where it can be dangerous , such as casting away constness of a passed const reference and therefore breaking the contract your functions signature provides.
If a const variable requires a change in value, then you have discovered a flaw in the design (under most, if not all, situations). If the design is yours, great! - you have an opportunity to improve your code.
If the design is not yours, good luck because the UB comment above is spot-on. In embedded systems, const variables may be placed in ROM. Performing tricks in an attempt to make such a variable writable lead to some spectacular failures. Furthermore, the problem extends beyond simple member variables. Methods and/or functions that are marked const may be optimized in such away that "lack of const-ness" becomes nonsensical.
(Take this "comment-as-answer" as a statement on the poor interview question.)