Difference Between Const. Pointer and Reference

Difference between const. pointer and reference?

There are 3 types of const pointers:

//Data that p points to cannot be changed from p
const char* p = szBuffer;

//p cannot point to something different.
char* const p = szBuffer;

//Both of the above restrictions apply on p
const char* const p = szBuffer;

Method #2 above is most similar to a reference.

There are key differences between references and all of the 3 types of const pointers above:

  • Const pointers can be NULL.

  • A reference does not have its own address whereas a pointer does.

    The address of a reference is the actual object's address.

  • A pointer has its own address and it holds as its value the address of the value it points to.

  • See my answer here for much more differences between references and pointers.

Why no const reference in C++ just like const pointer?

References in C++ differ from pointers in several essential ways. One of the difference is:

Once a reference is created, it cannot be later made to reference another object; it cannot be reseated. This is often done with pointers.

It means Reference are like similar (see the link at the end of this answer) to const pointer (not pointer to a const!) in C++...

int a = 5;
int& m = a; // Behaves similar to int * const m = &a;
// See the link at the bottom for the differences between const pointer and reference.

and hence, you can't change/rebind them to point to some other address. So, you don't need a explicit const qualifier for a reference and that's why it is disallowed by the compiler.

See this link to learn Why are references not reseatable in C++?. I have copied the accepted answer of the above link:

The reason that C++ does not allow you to rebind references is given in Stroustrup's "Design and Evolution of C++" :

It is not possible to change what a reference refers to after initialization. That is, once a C++ reference is initialized it cannot be made to refer to a different object later; it cannot be re-bound. I had in the past been bitten by Algol68 references where r1=r2 can either assign through r1 to the object referred to or assign a new reference value to r1 (re-binding r1) depending on the type of r2. I wanted to avoid such problems in C++.

EDIT:

See this link for Difference between const pointer and reference? (Thanks to @M.M for pointing out the ambiguity in my statement).

What is the difference between const int*, const int * const, and int const *?

Read it backwards (as driven by Clockwise/Spiral Rule):

  • int* - pointer to int
  • int const * - pointer to const int
  • int * const - const pointer to int
  • int const * const - const pointer to const int

Now the first const can be on either side of the type so:

  • const int * == int const *
  • const int * const == int const * const

If you want to go really crazy you can do things like this:

  • int ** - pointer to pointer to int
  • int ** const - a const pointer to a pointer to an int
  • int * const * - a pointer to a const pointer to an int
  • int const ** - a pointer to a pointer to a const int
  • int * const * const - a const pointer to a const pointer to an int
  • ...

And to make sure we are clear on the meaning of const:

int a = 5, b = 10, c = 15;

const int* foo; // pointer to constant int.
foo = &a; // assignment to where foo points to.

/* dummy statement*/
*foo = 6; // the value of a can´t get changed through the pointer.

foo = &b; // the pointer foo can be changed.

int *const bar = &c; // constant pointer to int
// note, you actually need to set the pointer
// here because you can't change it later ;)

*bar = 16; // the value of c can be changed through the pointer.

/* dummy statement*/
bar = &a; // not possible because bar is a constant pointer.

foo is a variable pointer to a constant integer. This lets you change what you point to but not the value that you point to. Most often this is seen with C-style strings where you have a pointer to a const char. You may change which string you point to but you can't change the content of these strings. This is important when the string itself is in the data segment of a program and shouldn't be changed.

bar is a constant or fixed pointer to a value that can be changed. This is like a reference without the extra syntactic sugar. Because of this fact, usually you would use a reference where you would use a T* const pointer unless you need to allow NULL pointers.

Constant pointer vs Pointer to constant

const int* ptr; 

declares ptr a pointer to const int type. You can modify ptr itself but the object pointed to by ptr shall not be modified.

const int a = 10;
const int* ptr = &a;
*ptr = 5; // wrong
ptr++; // right

While

int * const ptr;  

declares ptr a const pointer to int type. You are not allowed to modify ptr but the object pointed to by ptr can be modified.

int a = 10;
int *const ptr = &a;
*ptr = 5; // right
ptr++; // wrong

Generally I would prefer the declaration like this which make it easy to read and understand (read from right to left):

int const  *ptr; // ptr is a pointer to constant int 
int *const ptr; // ptr is a constant pointer to int

Const reference vs pointer to const

In the first example, you have a const pointer to a non-const int. This is, because const applies to the thing left of it, except there is nothing at the left side, then it applies to the right thing. Therefore, it's OK to increment the value, but it would be forbidden to increment the pointer (increment without dereferencing). In the second example, you try to increment a const reference, which is not allowed.

What is the functional difference between a const pointer (not a pointer to const) and a reference?

From a functional point of view pointers and references are indeed the same thing... they reference an object and are not a copy of that object.

The only real difference in addition to not being able to rebind a reference is that a pointer can be NULL (i.e. it can point to nothing) while a reference is assumed to always reference an object.

You technically can actually end up with a reference that is referencing no object (e.g. passing *p to a function expecting a reference where p is the null pointer) but this is "undefined behavior".

In other words pointers are more "flexible" than references and this allows the compiler to ignore

  • That a reference can change the object it's referencing
  • That a reference can have no object

And this can in some cases produce faster code (however for the second point de-referencing a null pointer is undefined behavior and not a runtime error; the compiler therefore is not mandated to generate code that does something special in this case: that a pointer can actually point to no object is indeed irrelevant from a code generation point of view because it's in the contract between programmer and compiler that this will never happen).

The "price" to pay for the added flexibility of rebinding and having NULLs is that the syntax is (somewhat gratuitously) more annoying.

If the pointer cannot be reassigned (because the pointer itself is const) then there are no practical differences whatsoever except for the more verbose-but-explicit syntax. This because despite being an object a const-declared pointer cannot be altered even using aliasing.

While from a syntactic point of view you can take the address of the const pointer, cast the address to an address of a non-const pointer and change the value pointed to, such an operation would be undefined behavior and whatever happens (e.g. ignoring the assignment) the compiler is going to be right if taken to court :-)

const pointers vs const references in C++

References are always const, so you don't need the const keyword for
them; it is, in fact, forbidden.

So you have:

S*                ps;   //  Non-const pointer to a non-const value
S const* psc; // Non-const pointer to a const value
S* const pcs; // Const pointer to a non-const value
S const* const pcsc; // Const pointer to a const value

, but only:

S&                rs;   //  (const) reference to a non-const value
S const& rsc; // (const) reference to a const value

The const which immediately follows the name of the type can be moved
to the beginning of the declaration, at the cost of some confusion to
the reader.



Related Topics



Leave a reply



Submit