What's the use of const variable members in C++? - c++

Are there any scenarios where a const variable member is useful in C++?
If you want to make an immutable class, the usual approach is to declare private members with get-only const functions to access their values. This has the advantage that the class can be copy assigned and so on. So in this case you don't need const variable members.
On the other hand, if the class has a const member variable, it won't get an automatic copy assignment operator. I don't see an scenario where this would be useful.

A main advantage of a const data member is the same as with a reference member (indeed a reference can be usefully thought of as a const pointer), namely that it forces initialization, unless the member is of a type with a user-defined default constructor. The compiler will insist on initialization. Still, I've never found that so useful that I've started doing it.
An alternative, if guaranteed initialization is what one desires, is to wrap the data member in a class that does not provide default construction. With this approach the data member can be assigned to, if it supports assignment.
Another advantage (of a const data member) is that it expresses an intended constraint, with compiler checking, and that's almost always good. The more constraints on how values can change, the less there is to consider to understand or debug the code.

Once you initialize a variable const then you never can re-initialized it. Each later attempt to re-initialize the const variable will produce a compilation error.
It is helpful when you want to prevent the accidental modification of some variable which you never want to be change. Like in mathematics we need PI, we can declared it as a constant -
private const double PI = 3.1416;

Related

Why can't static member functions be constant?

I went through the already existing thread on this topic and wasn't convinced with the explanation.
What I could pick up from there was:
When a non-static member function is declared const, the restriction is imposed on this this pointer. As static member functions donot involve the this pointer, they cannot be declared const.
Is that it? Doesn't sound too convincing to me. I mean, I'm not questioning why it's so. I just want to to the reason why.
A const non-static member function is allowed to modify local, static, and global variables; it just isn't allowed to modify members of its class through the this pointer (implicitly or explicitly). A const static member function, therefore, would be allowed to modify local, static, and global variables, just like a non-member function. This would make the const meaningless.
If you want to write a function that isn't allowed to modify any non-local variables at all, you can declare it constexpr, although that also imposes additional restrictions.
The reason the const/non-const distinction for functions is important is that there are contexts in which it is not legal to call a non-const function. So the distinction can be used to enforce invariants.
For example, if you pass a non-const reference to a function, if your class is properly designed, you are guaranteed that the function can't change the value of the thing the reference refers to. This allows you to avoid copies.
Also, a non-const reference can't bind to a temporary. This permits functions to signal whether they return values through references or just take a value. You will get an error at compile time if you inadvertently ignore a returned value because a temporary was created unexpectedly.
None of this would apply to static functions because there is no context in which you would be prohibited from calling them. So the entire rationale for the distinction does not exist with static functions.

volatile member function vs. constant member function in C++

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.

is it good practice to add const at end of member functions - where appropriate?

Is it a good practice, in C++, to add const at the end of a member function definition every time the function does not modify the object, i.e., every time the function is 'eligible' for const?
I know that it's necessary in this case:
class MyClass {
public:
int getData() const;
};
void function(const MyClass &m) { int a = m.getData(); dosomething... }
but other than this, and other uses of const for actual functionality, does adding const to the end actually change the way code is executed (faster/slower) or is it just a 'flag' for the compiler to handle cases such as the one above?
In other words, if const (at the end) is not needed for functionality in a class, does adding it make any difference?
Please see this excellent article about const correctness by Herb Sutter (C++ standards committee secretary for 10 years.)
Regarding optimizations, he later wrote this article where he states that "const is mainly for humans, rather than for compilers and optimizers." Optimizations are impossible because "too many things could go wrong...[your function] might perform const_casts."
However, const correctness is a good idea for two reasons: It is a cheap (in terms of your time) assertion that can find bugs; and, it signals the intention that a function should theoretically not modify the object's external state, which makes code easier to understand.
every time the function does not modify the object, i.e., every time the function is 'eligible' for const?
In my opinion, Yes. It ensures that you call such functions on const objects or const expressions involving the object:
void f(const A & a)
{
a.inspect(); //inspect must be a const member function.
}
Even if it modifies one or few internal variables once or twice, even then I usually make it const member function. And those variables are declared with mutable keyword:
class A
{
mutable bool initialized_cache; //mutable is must!
public:
void inspect() const //const member function
{
if ( !initialized_cache)
{
initialized_cache= true;
//todo: initialize cache here
}
//other code
}
};
Yes. In general, every function that is logically const should be made const. The only gray areas are where you modify a member through a pointer (where it can be made const but arguably should not be const) or where you modify a member that is used to cache a computation but otherwise has no effect (which arguably should be made const, but will require the use of the keyword mutable to do so).
The reason why it's incredibly important to use the word const is:
It is important documentation to other developers. Developers will assume that anything marked const does not mutate the object (which is why it might not be a good idea to use const when mutating state through a pointer object), and will assume that anything not marked const mutates.
It will cause the compiler to catch unintentional mutations (by causing an error if a function marked const unintintionally calls a non-const function or mutates an element).
Yes, it is a good practice.
At the software engineering level it allows you to have read-only objects, e.g. you can prevent objects from being modified by making them const. And if an object is const, you are only allowed to call const functions on it.
Furthermore, I believe the compiler can make certain optimizations if it he knows that an object will only be read (e.g., share common data between several instances of the object as we know they are never being modified).
The 'const' system is one of the really messy features of C++. It is simple in concept, variables declared with ‘const’ added become constants and cannot be altered by the program, but, in the way is has to be used to bodge in a substitute for one of the missing features of C++, it gets horridly complicated and frustratingly restrictive. The following attempts to explain how 'const' is used and why it exists. Of the mixes of pointers and ‘const’, the constant pointer to a variable is useful for storage that can be changed in value but not moved in memory and the pointer (constant or otherwise) is useful for returning constant strings and arrays from functions which, because they are implemented as pointers, the program could otherwise try to alter and crash. Instead of a difficult to track down crash, the attempt to alter unalterable values will be detected during compilation.
For example, if a function which returns a fixed ‘Some text’ string is written like
char *Function1()
{ return “Some text”;}
then the program could crash if it accidentally tried to alter the value doing
Function1()[1]=’a’;
whereas the compiler would have spotted the error if the original function had been written
const char *Function1()
{ return "Some text";}
because the compiler would then know that the value was unalterable. (Of course, the compiler could theoretically have worked that out anyway but C is not that clever.)
When a subroutine or function is called with parameters, variables passed as the parameters might be read from to transfer data into the subroutine/function, written to to transfer data back to the calling program or both to do both. Some languages enable one to specify this directly, such as having ‘in:’, ‘out:’ & ‘inout:’ parameter types, whereas in C one has to work at a lower level and specify the method for passing the variables choosing one that also allows the desired data transfer direction.
For example, a subroutine like
void Subroutine1(int Parameter1)
{ printf("%d",Parameter1);}
accepts the parameter passed to it in the default C & C++ way which is a copy. Therefore the subroutine can read the value of the variable passed to it but not alter it because any alterations it makes are only made to the copy and lost when the subroutine ends so
void Subroutine2(int Parameter1)
{ Parameter1=96;}
would leave the variable it was called with unchanged not set to 96.
The addition of an ‘&’ to the parameter name in C++ (which was a very confusing choice of symbol because an ‘&’ infront of variables elsewhere in C generate pointers!) like causes the actual variable itself, rather than a copy, to be used as the parameter in the subroutine and therefore can be written to thereby passing data back out the subroutine. Therefore
void Subroutine3(int &Parameter1)
{ Parameter1=96;}
would set the variable it was called with to 96. This method of passing a variable as itself rather than a copy is called a ‘reference’ in C.
That way of passing variables was a C++ addition to C. To pass an alterable variable in original C, a rather involved method using a pointer to the variable as the parameter then altering what it pointed to was used. For example
void Subroutine4(int *Parameter1)
{ *Parameter1=96;}
works but requires the every use of the variable in the called routine so altered and the calling routine altered to pass a pointer to the variable which is rather cumbersome.
But where does ‘const’ come into this? Well, there is a second common use for passing data by reference or pointer instead of copy. That is when copying a the variable would waste too much memory or take too long. This is particularly likely with large compound user-defined variable types (‘structures’ in C & ‘classes’ in C++). So a subroutine declared
void Subroutine4(big_structure_type &Parameter1);
might being using ‘&’ because it is going to alter the variable passed to it or it might just be to save copying time and there is no way to tell which it is if the function is compiled in someone else’s library. This could be a risk if one needs to trust the the subroutine not to alter the variable.
To solve this, ‘const’ can be used the in the parameter list like
void Subroutine4(big_structure_type const &Parameter1);
which will cause the variable to passed without copying but stop it from then being altered. This is messy because it is essentially making an in-only variable passing method from a both-ways variable passing method which was itself made from an in-only variable passing method just to trick the compiler into doing some optimization.
Ideally, the programmer should not need control this detail of specifying exactly how it variables are passed, just say which direction the information goes and leave the compiler to optimize it automatically, but C was designed for raw low-level programming on far less powerful computers than are standard these days so the programmer has to do it explicitly.
My understanding is that it is indeed just a flag. However, that said, you want to add it wherever you can. If you fail to add it, and a function elsewhere in your code does something like
void function(const MyClass& foo)
{
foo.getData();
}
You will run into issues, for the compiler cannot guarantee that getData does not modify foo.
Making member functions const ensures that calling code that has const objects can still call the function. It is about this compiler check - which helps create robust self-documenting code and avoid accidental modifications of objects - and not about run-time performance. So yes, you should always add const if the nature of the function is such that it doesn't need to modify the observable value of the object (it can still modify member variables explicitly prefixed with the mutable keyword, which is intended for some quirky uses like internal caches and counters that don't affect the client-visible behaviour of the object).

Good Practice: To Modify Only Function Parameters?

Say, I develop a complex application: Within object member functions, should I modify only those objects, that are passed to the member functions as parameters, or can I access and modify any other objects I have access to(say public or static objects)?
Technically, I know that it is possible to modify anything I have access to. I am asking about good practices.
Sometimes, it is bothering to pass as an argument everythying i will access and modify, especially if I know that the object member function will not be used by anybody else, but me. Thanks.
Global state is never a good idea (though it is sometimes simpler, for example logging), because it introduces dependencies that are not documented in the interface and increase coupling between components. Therefore, modifying a global state (static variables for example) should be avoided at all costs. Note: global constants are perfectly okay
In C++, you have the const keyword, to document (and have the compiler enforce) what can be modified and what cannot.
A const method is a guarantee that the visible state of an object will be untouched, an argument passed by const reference, or value, will not be touched either.
As long as it is documented, it is fine... and you should strive for having as few non-const methods in your class interface and as few non-const parameters in your methods.
If you have a class with member variables, then it is entirely acceptable to modify those member variables in a member method regardless of whether those member variables are private, protected, or public. This is want is meant by encapsulation.
In fact, modifying the variables passed into the member method is probably a bad idea; returning a new value is what you'd want, or getting a new value back from a separate member method.

C++ mutable appropriate in this case?

I would like to ask if the use of mutable is appropriate here:
#include <iostream>
class Base
{
protected:
int x;
public:
virtual void NoMod() const
{
std::cout << x << std::endl;
}
void Draw() const
{
this->NoMod();
}
};
class Derive : public Base
{
private:
mutable int y;
public:
void NoMod() const
{
y = 5;
}
};
int main()
{
Derive derive;
// Test virtual with derive
derive.Draw();
return 0;
}
The Base class is a 3rd-party library. I'm extending it to provide my own NoMod(). The library original NoMod() is declared as a const.
My NoMod() differs from Base in the fact that it needs to modify its own member variable.
Thus, for my own NoMod() to compile and get called when Draw() is called, I had to
1) Implement Derive::NoMod() as a const
2) make my int y mutable.
Is this the best I can do?
It's hard to say, since you don't give any context on what y refers to or how it's used.
In general, mutable is only appropriate when changing the mutable variable doesn't change the actual "value" of the object. For example, when I was writing a wrapper for C-style strings, I needed to make the internal mLength variable mutable so that I could cache the length, even if the thing it was requested on was a const object. It didn't change the length or the string, and wasn't visible outside of the class itself, so making it mutable was okay.
As 'head geek' described, the answer to your question depends on how your data member is used.
I distinguish two types of data members in a class.
I use the common term 'attribute' to refer to data members
that are the logical state or 'value' of the object.
Typically attributes are rarely declared as mutable.
I have coined the protologism 'contribute' it denote
data members that are simply 'working memory/storage'
and that are somewhat divorced from the state of the object.
Contributes have no contextual relevance to the user of the object,
they exist in the class only to contribute to the maintenance
and efficient operation of the object.
Contributes are usually declared in the class as mutable and are always
private or protected.
For example let's say your object is a linked list,
so you have a pointer to the first item in the list.
I would consider this pointer a contribute because
it does not represent the data in the list.
Even if the list is sorted and the
pointer is set to the new first item in the list,
the user of the list object could care less how the
list is maintained. Only that the list data has
been modified or not and that the the list is sorted or not is
relevant to the user's perspective.
Even if you had a booean data member 'sorted' to quickly determine
if the list is in a sorted state, that too would be a contribute
because it is the list structure itself which imbues the sorted state,
the 'sorted' variable member is used simply to efficiently remember the state
without having to scan the list.
As another example, if you have a const method that searches the list.
Suppose you know that typically the search will return the
most recently previously searched for item,
you would keep a pointer in your class to such a item so your method
can first check if the last found item matches the search key before searching
the entire list (if the method does indeed need to search the list and finds
an item, the pointer would be updated).
This pointer I would consider to be a contribute because it
is only there to help speed up the search. Even though the
search updates the pointer contribute, the method is effectively
const because none of the items' data in the container are modified.
So, data members that are attributes are usually not declared mutable,
and data members that contribute to the functioning of an object will usually be mutable.
The only time I think mutable is okay is for things like reference counts that aren't really part of the object's state.
If y is part of the object's physical state, but not logical state, then this is okay, but otherwise, don't do it.
Use mutable when the member of the class is not really defining the state of the object, (e.g. is a cached value/object that helps improving performance).
I use to do another difference. In your example, you only enforce change to const object only once. You can use also const_cast operator:
const_cast< Derive*>( this)->y = 10;
When you use const_cast operator, you have the advantage that you can easily identify the places where you enforced the const to non-const conversion by simply running a search in your code for the operator name.
However, as I said, if the member is not part of the state of the object, but must be changed indirectly in several constant methods, use mutable for that member.
The only situations where I needed the mutable feature are:
a cached version of derived data. For example, if you have a Rectangle class that has a GetSurface() member function that is likely to be called a lot, you could add a mutable m_surfaceCache member variable to keep the derived data.
a critical section member variable. This is because my CriticalSection::Enter() function is conceptually not const, but the critical section member variable is not a real part of the class data, it is more like a compiler guideline.
However, as a general rule of thumb, I'dd advise not to use mutable too often, as it bypasses C++'s wonderful const feature.
Another situation where you can think of 'mutable' is when you have a class with 'const' member variables and you require to implement the assignment operator(=) without skipping the assignment of the 'const' member.
Also, const_cast apllied on originally declared 'const' variable and using it is U.B. according to C++ standard. So if the interface of a method accepts a 'const' which has to be modified internally, pass it a 'mutable' argument.
You may judge the appropriateness of the same from the above situations i.e. only of it makes sense semantically! Do not use it to make the source-code compilable.
Regards,
If, as you said, it's part of a third party library, you may not have a choice. C++ is at heart a pragmatic language and lets you do what you need to do, even if it may not always be a "best practice".
One thing to note though, is that the third party library is documenting that NoMod should not modify the object by adding that const specifier. By violating that contract, you leave yourself open to possible trouble. If the library in some situations call NoMod multiple times, your derived class better be able to handle that, since a true const method would have no problem with it.
I'd first look for another way to solve the problem, but failing there declare it mutable.