The latter prevents you from modifying the_string
inside print_string
. It would actually be appropriate here, but perhaps the verbosity put off the developer.
char* the_string
: I can change which char
the_string
points to, and I can modify the char
to which it points.
const char* the_string
: I can change which char
the_string
points to, but I cannot modify the char
to which it points.
char* const the_string
: I cannot change which char
the_string
points to, but I can modify the char
to which it points.
const char* const the_string
: I cannot change which char
the_string
points to, nor can I modify the char
to which it points.
The email you linked to about "String" is wrong (and confusing).
Basically:
char*
is a pointer to an unbounded array of characters. Traditionally we consider such an array to be a C-string if it contains a set of valid characters followed by a \0
. There's no limit to the size of the array.
const char*
is a pointer to an unbounded array of immutable characters.
string*
is a pointer to a std::string
object, and is entirely different. This is a smart object that encapsulates a string. Using std::string
instead of C-strings can make your life loads easier, even though they've got some rough edges and a lot of nasty gotchas; they're well worth looking into, but they're not relevant to the question.
"String"
is a special expression that returns a const char*
pointing at the specific C-string (note: this is not actually true, but it's a simplification that lets me answer the question concisely).
A char*
can be automatically cast to a const char*
, but not vice versa. Note that old C++ compilers had a special exception to the type rules to let you do this:
char* s = "String";
...without producing a type error; this was for C compatibility. Modern C++ compilers won't let you do it (such as recent gccs). They require this:
const char* s = "String";
So. The problem here is that you've got:
throw "All parameters must be greater than 0.";
...but then you're trying to catch it with:
catch(char* e)
This doesn't work, because the throw is throwing a const char*
, which can't be cast to the type specified in the catch, so it isn't getting caught.
This is why changing the catch to:
catch (const char* e)
...makes it work.
Best Answer
The difference is that
const char *
is a pointer to aconst char
, whilechar * const
is a constant pointer to achar
.The first, the value being pointed to can't be changed but the pointer can be. The second, the value being pointed at can change but the pointer can't (similar to a reference).
There is also a
which is a constant pointer to a constant char (so nothing about it can be changed).
Note:
The following two forms are equivalent:
and
The exact reason for this is described in the C++ standard, but it's important to note and avoid the confusion. I know several coding standards that prefer:
over
(with or without pointer) so that the placement of the
const
element is the same as with a pointerconst
.