Const Object, Const Member Function and Mutable Variable in C++ - c++

I know that a const object can't call a non-const member function. It says so in the C++14 Standard (ISO/IEC 14882:2014) Section 9.3.2, Paragraph 3:
A cv-qualified member function can be called on an object-expression (5.2.5) only if the object-expression is as cv-qualified or less-cv-qualified than the member function.
Does this constraint make sense if the member function does not modify anything? Or if the member function modifies a mutable variable? For example:
class My_Class {
public:
mutable int value;
void function( int x ) const { value = x; } // Correct
//void function( int x ) { value = x; } // Not Correct
My_Class() : value(0) {}
};
int main(){
const My_Class obj;
obj.function( 1 );
return 0;
}
In this specific case, if the function is const, the program is correct and the function can modify a variable of the const object. If the function is not const, the program is not correct. So in the end, I need to write const to be able to modify something, which should be the opposite purpose of const.
Does anyone know why this rule is designed this way?

Does [Section 9.3.2, Paragraph 3 of] make sense if the member function does not modify anything? Or if the member function modifies a mutable variable?
Yes, it does. The caller of the function cannot in general know whether the function modifies any non mutable member. It knows whether the function is const or not, so the compiler can only make a decision based on that.
A non const function could modify the non mutable state, so you obviously may not call it on a const object. Whether the non const function does modify the state is irrelevant since it is an implementation detail that is not available when deciding if the call is allowed. In other words, constness is part of the interface of the function, while the implementation of the function is not part of the interface. The interface of the function is fully specified by its declaration.
An example:
struct C {
mutable int a;
int b;
void do_something();
};
const C c;
c.do_something();
Does it make sense to allow the call do_something? Does the fact that do_something might not modify b affect that? How could we assume that do_something does not modify b?
The answers are: It wouldn't make sense. It does not have an effect. There is no way we could make such assumption.
Writing a non const member function that doesn't modify any non mutable state - at least potentially or allow such modification indirectly by returning a non const reference / pointer to this - makes little sense, although the standard does permit doing so.
So in the end, I need to write const to be able to modify something, which should be the opposite purpose of const.
That might seem oxymoronic, but that is because it is an oversimplification. You need to write const to be able to modify the mutable state of a const object. The const that you write declares that you do not modify any non mutable state, and that declaration gives the permission to call it on const objects.
Your commented-out non-const function is still correct to use with non-const objects.

There is a fundamental misunderstanding in your question:
class My_Class {
public:
mutable int value;
void function( int x ) { value = x; } // Absolutely fine
My_Class() : value(0) {}
};
mutable does not mean "can only be modified in a const member function". It means "can be modified even in a const member function".

The mutable keyword,
Applies to non-static class members of non-reference non-const type and specifies that the member does not affect the externally visible state of the class (as often used for mutexes, memo caches, lazy evaluation, and access instrumentation). mutable members of const class instances are modifiable
You're questioning the validity of a C++ keyword. I feel the examples in this definition, provide positive proof that such a keyword is needed, and that mutable as imagined by the designers of the language is a boon to us.

Related

Should I declare method "const" if it is "shallow const" only, not "deep const"?

I have class Foo and its member bar_ is a pointer to some data. Method modify modifies the data, but not the pointer itself. Therefore I can declare the method as const:
class Foo {
public:
Foo() : bar_(new double) {};
void modify() const {*bar_ += 1;};
private:
double *bar_;
};
If I declare the method as const, it will accessible from other const methods, which is more flexible. At the same time I can drop const as a hint for other developers and users that method modifies the data indirectly (and let think that the data is owned by the class). So I have a choice here: declare modify as const or drop const: void modify() const or void modify().
What are pros and cons of each approach? What do guidelines say? What should I do?
const after a method declaration is a statement of intent - const methods are meant to be idempotent; they do not modify the state of the object and can be called on const instances.
If the value pointed-to by bar_ is part of the object's state, then a const method should not modify it.
In addition, even the name modify() sounds like it modifies the object in some way, and thus should not be declared const.
But also the other way is important - if a method does not modify the state, it is recommended to declare it const (see C++ Core Guideline Con.2).

Why modifiers like const not allowed on nonmember functions

I couldn't understand the reason for not allowing modifiers such as const or volatile to nonmembers functions.
Following is the example code I tired
class A
{
private:
int var;
public:
int func();
};
int A::func()
{
// Some calculation on using var
int temp = var + 10;
return temp;
}
void func2( const A& tempObj ) const;
void func2( const A& tempObj )
{
std::cout << "temp obj called : " << tempObj.func() << std::endl;
}
int main()
{
A aobj;
aobj.func();
func2( aobj );
return 0;
}
which throws an compiler error error C2270: 'func2' : modifiers not allowed on nonmember functions for void func2( const A& tempObj ) const;
I also get another error error C2662: 'A::func' : cannot convert 'this' pointer from 'const A' to 'A &' for tempObj.func() in func2 here I was assuming that the member function func will be called without any errors.
const modifier states that a member function won't modify data members of the object the function belongs to.
It's like an assurance that calling that function on an object aobj won't modify the internal state of that object. So, assuming that aobj is declared const too, you will still be able to invoke that function on it; on the contrary, you would not be able to invoke non const function members.
If a function is not member of a class, it makes no sense to apply const modifier. On another language, it could have meant that the function wasn't able to modify global variables, maybe; but that language is not C++.
Imagine that there is a hidden parameter on each non-static member function:
int A::func(A* this) {...}
If you declare a member function const or volatile, that is added to that hidden parameter, pretty much like the following:
int A::func(const A* this) {...}
Some languages like python make the instance parameter on the member functions explicit, so there you write def func(self): inside a class definition to declare non-static functions.
A const qualification on a class method declares that the method doesn't modify any (non-mutable) member variables.
It therefore just doesn't make any sense to declare that on a non-member function because there are no member variables for it to modify.
The const qualification is very useful because it explicitly indicates that it's safe to call this method on a const variable without breaching the constness of that variable.
In C++, the member function modifiers apply to the object on which the function is being called. That is the use the language has for these modifiers.
Non-member functions have no such object, so the qualification would make no sense. One could imagine the language allowing cv-qualifying non-members as having no effect, but in my mind this would only be confusing. One could also imagine the cv-qualifiers having a different meaning for non-members, but the reality is what it is. That is the way the language was designed.

Does a class with all attributes const need to have member function declared const as well?

The title already says all. Let me expand a little nevertheless: I've class whose all attributes are const:
template< class perm = Perm16 >
class PermutationGroup {
public:
using StrongGeneratingSet = std::vector< std::vector< perm > >;
const std::string name;
const uint64_t N;
const StrongGeneratingSet sgs;
PermutationGroup(std::string name, uint64_t N, StrongGeneratingSet sgs) :
name(name), N(N), sgs(sgs) { assert(check_sgs()); };
bool check_sgs() const; // defined as const
bool is_canonical(vect v) const; // defined as const
[...]
};
Is it of any use to define all member function as const as well ? Or am I needlessly repeating myself ?
If you do not declare the member functions as const, you can't invoke them on const objects or objects referenced by a const reference. For example, the following won't work:
const PermutationGroup& group = PermutationGroup("foobar", 42, ...);
group.check_sgs(); // ERROR: can't invoke non-const function on const objects
Declaring your methods as const means that you can call them on a const-qualified object. It's not necessary to declare them const just because there are no mutable fields in the class, but in general, it's easier to write const-correct code if you always declare methods that don't modify anything as const.
Does a class with all attributes const need to have member function declared const as well?
Declaring a member variable const is different than declaring a member function const. When a member variable is declared const it cannot be modified. It can still be accessed by member functions even those not declared const, they just can't be modified.
Decalring a member function const is saying this function does not modify this object. The function is not allowed to change any member variable unless it's declared mutable. It also cannot call member functions that are not declared const as those functions would be allowed to modify the object.
Declaring member functions as const is important as it allows those functions to be called on constant instances of the class they belong to. Nosid provides a great example in their answer.
No it does not.
That been said, constness on behalf of the attributes implies constness on behalf of the instance, so even if a member function is non const it won't be able to behave as such (ie cause state mutation)
The other way around is not true though. For example
int myClass::example() const {
member = 1;
}
is the same as
int myClass::example() const {
this->member = 1;
}
and constness of the member function means constness of this pointer. This is slightly different from promising that the "raw bits" of the object's struct aren't going to change. For example, reference members can be modified by const member functions
To sum up : Declaring a member function as const becomes mandatory when it's to be used with a this pointer that is const. In your case, not declaring one as const would just be futile (and break the inspector / mutator semantics .. that being less of a deal).

Using 'const' in class's functions [duplicate]

This question already has answers here:
Meaning of 'const' last in a function declaration of a class?
(12 answers)
Closed 5 years ago.
I've seen a lot of uses of the const keyword put after functions in classes, so i wanted to know what was it about. I read up smth at here: http://duramecho.com/ComputerInformation/WhyHowCppConst.html .
It says that const is used because the function "can attempt to alter any member variables in the object" . If this is true, then should it be used everywhere, because i don't want ANY of the member variables to be altered or changed in any way.
class Class2
{ void Method1() const;
int MemberVariable1;}
So, what is the real definition and use of const ?
A const method can be called on a const object:
class CL2
{
public:
void const_method() const;
void method();
private:
int x;
};
const CL2 co;
CL2 o;
co.const_method(); // legal
co.method(); // illegal, can't call regular method on const object
o.const_method(); // legal, can call const method on a regulard object
o.method(); // legal
Furthermore, it also tells the compiler that the const method should not be changing the state of the object and will catch those problems:
void CL2::const_method() const
{
x = 3; // illegal, can't modify a member in a const object
}
There is an exception to the above rule by using the mutable modifier, but you should first get good at const correctness before you venture into that territory.
Others have answered the technical side of your question about const member functions, but there is a bigger picture here -- and that is the idea of const correctness.
Long story short, const correctness is about clarifying and enforcing the semantics of your code. Take a simple example. Look at this function declaration:
bool DoTheThing(char* message);
Suppose someone else wrote this function and you need to call it. Do you know what DoTheThing() does to your char buffer? Maybe it just logs the message to a file, or maybe it changes the string. You can't tell what the semantics of the call are by just looking at the function declaration. If the function doesn't modify the string, then the declaration is const incorrect.
There's practical value to making your functions const correct, too. Namely, depending on the context of the call, you might not be able to call const-incorrect functions without some trickery. For example, assume that you know that DoTheThing() doesn't modify the contents of the string passed to it, and you have this code:
void MyFunction()
{
std::string msg = "Hello, const correctness";
DoTheThing(msg.c_str());
}
The above code won't compile because msg.c_str() returns a const char*. In order to get this code to compile, you would have to do something like this:
void MyFunction()
{
std::string msg = "Hello, const correctness";
DoTheThing(msg.begin());
}
...or even worse:
void MyFunction()
{
std::string msg = "Hello, const correctness";
DoTheThing(const_cast<char*>(msg.c_str()));
}
neither of which, arguably, are 'better' than the original code. But because DoTheThing() was written in a const-incorrect way, you have to bend your code around it.
The meaning is that you guarantee to clients calling a const function member that the state of the object will not change. So when you say a member function is const it means that you do not change any of the objects member variables during the function call.
const, when attached to a non-static class method, tells the compiler that your function doesn't modify the internal state of the object.
This is useful in two ways:
If you do write code that changes internal state in your const method, the compiler catches the error, moving a programming error from run-time to compile-time.
If client code calls a non-const method on a constant pointer, the compiler catches the error, ensuring the "chain of not changing things" is maintained.
Typically you want to declare all non-mutating non-static class methods as const. This allows calling code to use the const qualifier on pointers, and it helps catch mistakes.
Typical C++: you can declare a class member variable "mutable" and then change it even from a const method.
The const keyword used after a method indicate that this method doesn't modify the object on which it's called. This way, this method can be called on a const version of the object.
If this is true, then should it be used everywhere, because i don't want ANY of the member variables to be altered or changed in any way?
Well, no. Sometimes you do want instance methods to modify members. For example, any set method will obviously need to set variables, so it's not the case that you should put const everywhere. But if your object's state is totally immutable, first consider whether it might not be better to have no instances at all (i.e., a static class), and if that's not the case, then make everything const.
It's quite unusual not to want to have any member variables changed, but if that's what your class requires, then you should make all your member functions const.
However, you probably do want to change at least some members:
class A {
private:
int val;
public:
A() : val(0) {}
void Inc() { val++; }
int GetVal() const { return val; };
};
Now if I create two instances of A:
A a1;
const A a2;
I can say:
a1.GetVal();
a2.GetVal();
but I can only say:
a1.Inc();
trying to change the value of a constant object:
a2.Inc();
gives a compilation error.

What does the const operator mean when used with a method in C++?

Given a declaration like this:
class A {
public:
void Foo() const;
};
What does it mean?
Google turns up this:
Member functions should be declared with the const keyword after them if they can operate on a const (this) object. If the function is not declared const, in can not be applied to a const object, and the compiler will give an error message.
But I find that somewhat confusing; can anyone out there put it in better terms?
Thanks.
Consider a variation of your class A.
class A {
public:
void Foo() const;
void Moo();
private:
int m_nState; // Could add mutable keyword if desired
int GetState() const { return m_nState; }
void SetState(int val) { m_nState = val; }
};
const A *A1 = new A();
A *A2 = new A();
A1->Foo(); // OK
A2->Foo(); // OK
A1->Moo(); // Error - Not allowed to call non-const function on const object instance
A2->Moo(); // OK
The const keyword on a function declaration indicates to the compiler that the function is contractually obligated not to modify the state of A. Thus you are unable to call non-const functions within A::Foo nor change the value of member variables.
To illustrate, Foo() may not invoke A::SetState as it is declared non-const, A::GetState however is ok because it is explicitly declared const. The member m_nState may not be changed either unless declared with the keyword mutable.
One example of this usage of const is for 'getter' functions to obtain the value of member variables.
#1800 Information: I forgot about mutable!
The mutable keyword instructs the compiler to accept modifications to the member variable which would otherwise cause a compiler error. It is used when the function needs to modify state but the object is considered logically consistent (constant) regardless of the modification.
This is not an answer, just a side comment. It is highly recommended to declare variables and constants const as much as possible.
This communicates your intent to users of your class (even/especially yourself).
The compiler will keep you honest to those intentions. -- i.e., it's like compiler checked documentation.
By definition, this prevents state changes you weren't expecting and can, possibly, allow you to make reasonable assumptions while in your methods.
const has a funny way of propagating through your code. Thus, it's a really good idea to start using const as early and as often as possible. Deciding to start const-ifying your code late in the game can be painful (easy, but annoying).
If you're using a language with static, compile time checks it's a great idea to make as much use of them as possible... it's just another kind of testing really.
Functions with const qualifier are not allowed to modify any member variables. For example:
class A
{
int x;
mutable int y;
void f() const
{
x = 1; // error
y = 1; // ok because y is mutable
}
};
C++ objects can be declared to be const:
const A obj = new A();
When an object is const, the only member functions that can be called on that object are functions declared to be const. Making an object const can be interpreted as making the object readonly. A const object cannot be changed, i.e. no data members of the object can be changed. Declaring a member function const means that the function is not allowed to make any changes to the data members of the object.
Two suggested best practices from experience:
(1) Declare const functions whenever possible. At first, I found this to be just extra work, but then I started passing my objects to functions with signatures like f(const Object& o), and suddenly the compiler barfed on a line in f such as o.GetAValue(), because I hadn't marked GetAValue as a const function. This can surprise you especially when you subclass something and don't mark your version of the virtual methods as const - in that case the compile could fail on some function you've never heard of before that was written for the base class.
(2) Avoid mutable variables when it's practical. A tempting trap can be to allow read operations to alter state, such as if you're building a "smart" object that does lazy or asynchronous i/o operations. If you can manage this with only one small mutable variable (like a bool), then, in my experience, this makes sense. However, if you find yourself marking every member variable as mutable in order to keep some operations const, you're defeating the purpose of the const keyword. What can go wrong is that a function which thinks it's not altering your class (since it only calls const methods) my invoke a bug in your code, and it could take a lot of effort to even realize this bug is in your class, since the other coder (rightly) assumes your data is const because he or she is only calling const methods.
const has a funny way of propagating through your code. Thus, it's a really good idea to start using const as early and as often as possible. Deciding to start const-ifying your code late in the game can be painful (easy, but annoying).
Additionally, you will easily run into problems if methods that should be const aren't! This will creep through the code as well, and make it worse and worse.
that will cause the method to not be able to alter any member variables of the object