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 intint const *
- pointer to const intint * const
- const pointer to intint 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 intint ** const
- a const pointer to a pointer to an intint * const *
- a pointer to a const pointer to an intint const **
- a pointer to a pointer to a const intint * 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 NULL
s 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
How to Do Input Validation in C++ with Cin
How Are Local and Global Variables Initialized by Default
Std::Map Default Value for Build-In Type
How to Know If a Type Is a Specialization of Std::Vector
Call Destructor and Then Constructor (Resetting an Object)
How to Use Std::Imbue to Set the Locale for Std::Wcout
Get Current Username in C++ on Windows
Why Does a Push_Back on an Std::List Change a Reverse Iterator Initialized with Rbegin
How to Get the Executable Name of a Window
Does (W)Ifstream Support Different Encodings
If Temporaries Are Implicitly Non-Modifiable, How Does This Work
Easiest Way of Using Min Priority Queue with Key Update in C++
Passing Variable Number of Arguments with Different Type - C++
Are Class Members Guaranteed to Be Contiguous in Memory
What Is Different Between Join() and Detach() for Multi Threading in C++