8

I read a post about how const storage works.

How does const storage work? (Item 2, Scott Myers Effective C++)

This says that each segment has separate section of write protected memory and const data goes there.

But what happens in case of references? I want to understand three scenarios.

  1. Global const reference.
  2. const reference in method.
  3. const reference in a class.

And for that matter pointers, I mean even though pointer can be stored in some write protected section, then how different versions of consts maintained.

such as

char x = 'z';
//following can not change the data of x, but ptr itself can change.
const char* ptr = &x;
char y = '9';
ptr = &y;

above is allowed but following is not

char* const ptr1 = &x;
ptr1 = &y;

How this is handled?

1

4 Answers 4

18

There are two aspects to the const in C++:

  • logical constness: When you create a variable and point a const pointer or reference to it, the compiler simply checks that you don't modify the variable via the const pointer or reference, directly or indirectly. This constness can be cast away with a const_cast<>. As such, the following code is perfectly legal:

    char myString[] = "Hallo Welt!";    //copy the string into an array on the stack
    const char* constPtr = myString;
    const_cast<char*>(constPtr)[i] = 'e';    //perfectly legal
    
  • physical constness: When you create a variable in static storage that is const, you allow the compiler to put in into non-writable memory. It may do so, or it may not. As far as the standard is concerned, you are simply invoking undefined behavior if you cast away constness to modify such an object. This includes all string literals, so the following code may or may not work:

     const char* myString = "Hallo World!";
     const_cast<char*>(myString)[1] = 'e';     //Undefined behavior, modifying a const static object!
    
2
  • Typical effects of undefined behaviour when you modify a const object: 1. Crash. 2. The object is not modified. 3. The object is modified, but the compiler assumes it isn't. So if you initialise const int x = 3; and you manage to change it to 4, the compiler will often assume that x = 3, but sometimes use the changed value 4, with entertaining results.
    – gnasher729
    Commented May 23, 2015 at 23:08
  • @gnasher729: Also 4. Some unrelated other object it happens to share storage with is also modified. There is string-pooling, and rarer general constant pooling. Commented May 24, 2015 at 22:14
7

When using the qualifier const as inthe case below:

 const int value=67;

We are telling the compiler that we promise not to change the value of the variable "value". As such the compiler will merely replace instances of "value" with the actual value we initialized it with.since the compiler replaces each instance of the variable with its actual value, we must initialize it.

  const int k; //error,must be initialized.

when bounding such a value to a reference, the reference must have such a qualifier to ensure we do not modify the value bound to through the reference(lvalue reference).

 const int& c1=value;
 c1=56; //error,we cannot modify it through the reference.

but we can also bind a non-const value to a const reference...

int i=89;
const int& ic=i; //const lvalue-ref
int& ir=i;
ir=7; //ok.ir is not const
ic=67990; //error ic is const

As for pointers:

 const int val=90;
 int* valp=&val;//error the pointer is not const.
 const int* val2p=&val;//ok as they are both const
 *val2p =788;//error as it is a pointer to non-writable space

However, a pointer to a const can be used to point to a non-const object.The idea is that pointers and references to const "think they point to or refer to const objects".

Unlike references, pointers are objects and can be made const. Meaning that a pointer can be made to point to a particular memory and not be allowed to point to another memory once initialized.

 int* const x=&val;//it will point to that memory location only.

The fact that "x" is itself a pointer does not say anything about the value it points to.

The other interesting case is the "constexpr" case:

 constexpr int* i=nullptr; //it is the pointer that is const.not the value it points to
 constexpt const int* ii=&value; //both are const in this case.
0

Strictly speaking, const x merely asks the compiler to check at compile time that you aren't changing x after its initial definition. This does not imply any change to the runtime behavior of the program, or any requirement to store x's value differently. A smart compiler will try to take advantage of that for some optimizations, but in the general case the machine code it generates for a const value, pointer or reference may be exactly the same as for a non-const value, pointer or reference. The only distinction between const char* and char* const is that the compiler performs a different check.

In fact, the main optimization here is not putting "const variables" in the static read-only program memory, but putting literal values there. In the sample you gave, the 'z' and the '9' characters are likely to exist somewhere in the compiled binary, regardless of what variables you did or did not use the const keyword on. If you use longer strings, you should be able to find them in the binary quite easily with a hex editor.

When you assign that literal to const x, the compiler will probably try to perform the additional optimization of not representing x as a separate location in memory, and instead interpreting all reads of x as reads of that literal value in the program code. But it would probably try to do that even if x happened to be non-const, since it can still see that you never assign anything to it (if it didn't, it wouldn't be able to enforce x's const-ness when you do declare it const). And it's probably also storing some intermediate values in CPU registers to avoid reading from any memory at all, so the actual machine code will vary pretty wildly.

It's worth noting that a lot of C++ features work the same way. A class method being private is also "just" a compile-time check.

0

Const keyword is directive to compiler that its initial value will never change. Compiler checks if during compiling if program is modifying the value by any way. Please clear your understanding about constant variable and write protected variables are entirely different things. It is similar to textbook definition of "Variable"

In programming, a variable is a value that can change, depending on conditions or on information passed to the program. Typically, a program consists of instruction s that tell the computer what to do and data that the program uses when it is running.

But actually variables is name given to memory location and it can be constant also.

Not the answer you're looking for? Browse other questions tagged or ask your own question.