How does the const qualification on variables differ in C and C++?
from: Does "const" just mean read-only or something more?
"What prompted this question was this answer: https://stackoverflow.com/questions/4024318#4024417 where he states const "just" means read-only in C. I thought that's all const meant, regardless of whether it was C or C++. What does he mean?"
const
in C cannot be used to build constant expressions.
For example :
#include <stdio.h>
int main()
{
int i = 2;
const int C = 2;
switch(i)
{
case C : printf("Hello") ;
break;
default : printf("World");
}
}
doesn't work in C because case label does not reduce to an integer constant.
const
means that you promise not to mutate the variable. It could still be changed.
class A {
public:
A(const int& a);
int getValue() const;
void setValue(int b);
private:
const int& a;
};
A::A(a) : a(a) {}
int A::getValue() const {
return a;
}
void A::setValue(int b) {
a = b; // error
}
int main() {
int my_a = 0;
A a(my_a);
std::cout << a.getValue() << std::endl; // prints 0
my_a = 42;
std::cout << a.getValue() << std::endl; // prints 42
}
No method A::*
may change a
, but main
can. That much is identical between C and C++.
What C++ does have are a couple (limited) ways to bypass const
, which are supposed to discourage programmers from discarding const
inappropriately.
Take a class like this.
class A {
public:
A();
int getValue();
private:
static int expensiveComputation();
int cachedComputation;
};
A::A() : cachedComputation(0) {}
A::getValue() {
if (cachedComputation == 0)
cachedComputation = expensiveComputation();
return cachedComputation;
}
cachedComputation
implicitly means this->cachedComputation
. Keep this in mind.
int main() {
A a1;
const A a2;
std::cout << a1.getValue() << std::endl;
std::cout << a2.getValue() << std::endl; // error
}
a2.getValue()
is illegal, because a non-const
method is being called on a const A a2
. One could cast away the const
-ness…
std::cout << ((A&)a2).getValue() << std::endl; // C-style cast
std::cout << const_cast<A&>(a2).getValue() << std::endl; // C++-style cast
The second is preferred, because the compiler will check that only the const
-ness is being casted, nothing else. However, this is still not ideal. Instead, there should be a new method added to the class.
class A {
public:
int getValue() const;
};
A::getValue() const {
if (cachedComputation == 0)
cachedComputation = expensiveComputation(); // error
return cachedComputation;
}
Now there is a const
method, so a2.getValue()
is fine. However, the trailing const
means that the method is given a const A *this
pointer, not an A *this
pointer like usual, making this->cachedComputation
a const int &
that cannot be mutated.
const_cast
could be applied inside the method, but better would be to change this one member's declaration.
class A {
private:
mutable int cachedComputation;
};
Now, even with a const A *this
, this->cachedComputation
can be mutated without casting.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With