There are plenty of other answers here, but I'm driven to post this because I feel that many of them provide too much detail, wander off topic, or assume knowledge of C++ jargon that the OP almost certainly doesn't have. I think that's unhelpful to the OP and others at a similar phase of their careers so I'm going to try to cut through some of that.
The situation itself is actually very straightforward. The declaration:
const SomeClassOrType *p = ...
simply says that whatever p is pointing to cannot be modified through that pointer, and that is useful to ensure that code that gains access to that object via p doesn't modify it when it isn't supposed to. It is most often used in parameter declarations so that functions and methods know whether or not they can modify the object being passed in (*).
It says nothing at all about the const-ness of what is actually being pointed to. The pointer itself, being just a simple soul, does not carry that information around with it. It only knows that, so far as the pointer is concerned, the object pointed to can be read from but not written to.
Concrete example (stolen from CiaPan):
void PrintString (const char *string);
char string [] = "abcde";
const char *p = string;
PrintString (p);
void PrintString (const char *ptr_to_string)
{
ptr_to_string [0] = 0; // oops! but the compiler will catch this, even though the original string itself is writeable
}
You can just pass string
to PrintString
directly of course, same difference, because the parameter is also declared const.
Another way to look at this is that const
is information provided by the programmer to help the compiler check the correctness / consistency of the code at compile time. It lets the compiler catch mistakes like the one above, and perhaps perform better optimisations. By the time you actually run your code, it is history.
(*) The modern idiom is probably to use a const reference, but I don't want to muddy the waters by throwing that into the main discussion.