Or is there some other protection against modifying them?
It makes sense if they are in read-only memory - that's the reason for making them const
, right?
Or is there some other protection against modifying them?
It makes sense if they are in read-only memory - that's the reason for making them const
, right?
const
is a compile time construct and isn't known about at runtime. It is only there to help the programmer reason about his program and to prevent bugs being introduced by altering things that were not supposed to be altered. const
tells the compiler that you don't want to allow this variable to be changed, and so the compiler will enforce it.
No they are not required to be. const
is compile time, and allow compiler to perform some kind of optimization. However, it is not mandatory that a variable be placed into a read-only memory location.
See this example, which is Undefined Behaviour (Thanks to Dyp for pointing that out):
#include <iostream>
int main()
{
const int bla = 42;
int *ptr = const_cast<int *>(&bla);
std::cout << *ptr << std::endl;
*ptr = 21;
std::cout << *ptr << std::endl;
}
It will output 42
and 21
, but it could also crash.
Now see this one:
#include <iostream>
int main()
{
const int bla = 42;
int *ptr = const_cast<int *>(&bla);
std::cout << bla << std::endl;
*ptr = 21;
std::cout << bla << std::endl;
}
On my compiler, this output 42
and 42
, because the compiler made some optimizations. Note that it could still crash because of *ptr = 21
;
There are a lot of cases where it's not possible for the compiler to make a const
into read-only memory (assuming there is read-only memory in the system in the first place). In fact, I believe nearly all compilers, as a rule, makes const
objects live in regular data (or stack) memory, just like ordinary variables.
The main purpose of const
is to declare your intent with the compiler that you do not want to and aren't supposed to change some value. I don't see any reason why compilers can't, under limited circumstances, put const
variables in read-only memory. But I also wouldn't rely on this - the standard certainly makes this possible, since it mentions that using const_cast
remove const
from an object that was originally marked const
, and then writing to it is undefined behaviour (so, it doesn't require the compiler to allow the value to be modified after using const_cast
to remove the original const
- and thus does allow for "Crash because we tried to write to read-only memory").
But consider this:
class X
{
int x;
public:
X(int v) : x(v) {}
}
int c = rand();
const X a(c+1);
const X b(c+2);
In this case, the compiler can't know the value in c
that it got from rand
, so it can't initialize a
and b
at compile time.
The const
keyword has two uses:
const
in read-only memory as long as the object has no mutable
members (i.e. the entire object is the object's state).That is why const_cast
ist allowed to strip away the const qualifier, but a requirement is that the object definition itself is not const
. Wikipedia on const correctness states that "However, any attempt to modify an object that is itself declared const by means of const_cast results in undefined behavior according to the ISO C++ Standard.".
As far as the standard is concerned, there's no requirement to place const
variables into write-protected RAM. const
is basically just compiler-enforced documentation.
Practically, if a value can be computed entirely at compile-time, compilers will usually use read-only storage for a const
variable. Otherwise, they're placed into the same read-write heaps or stacks as everything else.
Not only does the C++ standard not guarantee that const
objects are in read-only memory, it would be difficult for an implementation to implement completely, as explained below.
It would be difficult for a C++ implementation to place const
objects with automatic storage duration whose addresses are taken in read-only memory. This is because each different object must have a different address (because their pointers must compare unequal). So each such object must be created each time the block it is in is executed.
If a const
object’s address is not taken, the compiler can implement the multiple instances of it (in the C++ computational model) using only a single instance in memory (because every instance is identical and does not change). So such an object can be created once at program start-up (likely by loading from a constant-data section of the program file), marked read-only, and left unchanged for the duration of program execution. However, if an object’s address is taken (and used in observable ways), then the compiler must create each separate instance of the object (or somehow “fake” that one instance has multiple addresses). In general, a compiler cannot predict how many executions of a block may exist simultaneously (e.g., when there are recursive function calls). So it cannot create, at program start-up, all the instances of an object that are needed. They must be created on the fly.
Creating objects requires modifying memory, to write the initial values of the objects. Therefore, putting const
objects with automatic storage duration in read-only memory would require frequently changing memory from read-only to writeable and back. To create a new object, the program would have to change the read-only memory to writeable memory, write the initial value of a new object, and change the memory back to read-only.
Furthermore, this would give the appearance of read-only memory only for single-threaded programs without signal handlers. Programs with multiple threads of execution or single handlers might be able to observe the memory while it is in the writeable state.
No. Consider a const
object with a mutable
member. As mentioned const is a compile time construct to help the programmer convey intent.
If they were in read only memory, it would prevent const_cast
from being useful and meaningful, so code like this would not be possible, passing a const
variable to a function with a non-const
parameter: -
void print (char * str)
{
cout << str << endl;
}
int main ()
{
const char * c = "test text";
print ( const_cast<char *> (c) );
return 0;
}
Note that the print function could actually change the value in the originally defined const
variable c
.
const
is a mark for compiler. During compiling, compiler adds constants into separate group and checks for attempts to change it. If some function tries to do that, you will get compiler error.
However it is possible to trick compiler and change const
value using pointers and const_cast
but as a result of this you trick not compiler but yourself (or colleague).
As I said, to my friend who've been looking how to change const
value. const
is not for compiler only, it is much more for developer then compiler, because it shows, what data will not be changed.