An example of where a const pointer is highly applicable can be demonstrated thusly. Consider you have a class with a dynamic array inside it, and you want to pass the user access to the array but without granting them the rights to change the pointer. Consider:
#include <new>
#include <string.h>
class TestA
{
private:
char *Array;
public:
TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
~TestA(){if(Array != NULL){ delete [] Array;} }
char * const GetArray(){ return Array; }
};
int main()
{
TestA Temp;
printf("%s\n",Temp.GetArray());
Temp.GetArray()[0] = ' '; //You can still modify the chars in the array, user has access
Temp.GetArray()[1] = ' ';
printf("%s\n",Temp.GetArray());
}
Which produces:
Input data
put data
But if we try this:
int main()
{
TestA Temp;
printf("%s\n",Temp.GetArray());
Temp.GetArray()[0] = ' ';
Temp.GetArray()[1] = ' ';
printf("%s\n",Temp.GetArray());
Temp.GetArray() = NULL; //Bwuahahahaa attempt to set it to null
}
We get:
error: lvalue required as left operand of assignment //Drat foiled again!
So clearly we can modify the array's contents, but not the array's pointer. Good if you want to make sure the pointer has a consistent state when passing it back to the user. There is one catch, though:
int main()
{
TestA Temp;
printf("%s\n",Temp.GetArray());
Temp.GetArray()[0] = ' ';
Temp.GetArray()[1] = ' ';
printf("%s\n",Temp.GetArray());
delete [] Temp.GetArray(); //Bwuahaha this actually works!
}
We can still delete the pointer's memory reference, even if we can't modify the pointer itself.
So if you want the memory reference to always point to something (IE never be modified, similar to how a reference currently works), then it's highly applicable. If you want the user to have full access and modify it, then non-const is for you.
Edit:
After noting okorz001 comment of not being able to assign due to GetArray() being a right-value operand, his comment is entirely correct, but the above still applies if you were to return a reference to the pointer (I suppose I assumed GetArray was referring a reference), for example:
class TestA
{
private:
char *Array;
public:
TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
~TestA(){if(Array != NULL){ delete [] Array;} }
char * const &GetArray(){ return Array; } //Note & reference operator
char * &GetNonConstArray(){ return Array; } //Note non-const
};
int main()
{
TestA Temp;
Temp.GetArray() = NULL; //Returns error
Temp.GetNonConstArray() = NULL; //Returns no error
}
Will return in the first resulting in an error:
error: assignment of read-only location 'Temp.TestA::GetArray()'
But the second will occur merrily despite potential consequences on the underneath.
Obviously, the question will be raised 'why would you want to return a reference to a pointer'? There are rare instances where you need to assign memory (or data) directly to the original pointer in question (for example, building your own malloc/free or new/free front-end), but in those instances it's a non-const reference. A reference to a const pointer I've not come across a situation that would warrant it (unless maybe as declared const reference variables rather than return types?).
Consider if we have a function that takes a const pointer (versus one that doesn't):
class TestA
{
private:
char *Array;
public:
TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
~TestA(){if(Array != NULL){ delete [] Array;} }
char * const &GetArray(){ return Array; }
void ModifyArrayConst(char * const Data)
{
Data[1]; //This is okay, this refers to Data[1]
Data--; //Produces an error. Don't want to Decrement that.
printf("Const: %c\n",Data[1]);
}
void ModifyArrayNonConst(char * Data)
{
Data--; //Argh noo what are you doing?!
Data[1]; //This is actually the same as 'Data[0]' because it's relative to Data's position
printf("NonConst: %c\n",Data[1]);
}
};
int main()
{
TestA Temp;
Temp.ModifyArrayNonConst("ABCD");
Temp.ModifyArrayConst("ABCD");
}
The error in the const produces thus message:
error: decrement of read-only parameter 'Data'
Which is good as we probably don't want to do that, unless we want to cause the problems denoted in the comments. If we edit out the decrement in the const function, the following occurs:
NonConst: A
Const: B
Clearly, even though A is 'Data[1]', it's being treated as 'Data[0]' because the NonConst pointer permitted the decrement operation. With the const implemented, as another person writes, we catch the potential bug before it occurs.
One other main consideration, is that a const pointer can be used as a pseudo reference, in that the thing the reference points to cannot be changed (one wonders, if perhaps this was how it was implemented). Consider:
int main()
{
int A = 10;
int * const B = &A;
*B = 20; //This is permitted
printf("%d\n",A);
B = NULL; //This produces an error
}
When attempting to compile, produces the following error:
error: assignment of read-only variable 'B'
Which is probably a bad thing if a constant reference to A was wanted. If B = NULL
is commented out, the compiler will happily let us modify *B
and therefore A. This might not seem useful with ints, but consider if you had a single stance of a graphical application where you wanted an unmodifiable pointer that referred to it that you could pass around.
It's usage is variable (excuse the unintended pun), but used correctly, it is another tool in the box to assist with programming.