const pointer assign to a pointer
There is difference between constant pointer and pointer to constant. Constant pointer is a pointer (a number - memory address) that cannot be changed - it always point to the same object given via initialization:
int * const const_pointer = &some_int_var; // will be always pointing to this var
const_pointer = &some_other_var; // illegal - cannot change the pointer
*const_pointer = 2; // legal, the pointer is a pointer to non-const
Pointer to constant is a pointer whose pointed value cannot be changed:
const int * pointer_to_const = &some_int_var; // doesn't have to be always pointing to this var
pointer = &some_other_var; // legal, it's not a constant pointer and we can change it
*pointer = 2; // illegal, pointed value cannot be changed
You can always assign constant to variable i.e. const pointer to non-const pointer (a). You can cast pointer to non-const to a pointer to const (b). But you cannot cast pointer to const to a pointer to non-const (c):
int * pointer;
int * const const_pointer = &var;
const int * pointer_to_const;
/* a */
pointer = const_pointer; // OK, no cast (same type)
/* b */
pointer_to_const = pointer; // OK, casting 'int*' to 'const int*'
/* c */
pointer = pointer_to_const; // Illegal, casting 'const int*' to 'int*'
[EDIT] Below, this is not standard c++. However, this is common.[/EDIT]
String literal
"Hello"
is converted to constant pointer to const (const char * const
):
char *pointer = "Hello"; // Illegal, cannot cast 'const char*' to 'char*'
char * const const_pointer = "Hello"; // Illegal, cannot cast 'const char*' to 'char*'
const char * pointer_to_const = "Hello"; // OK, we can assign a constant to a variable of the same type (and the type is 'const char*')
"Hello" = pointer_to_const; // Illegal cannot re-assign a constant
In above examples the second is your case. You tried to initialize pointer-to-non-const with a pointer-to-const when passing string literal as argument of your function. No matter if these pointers are constants or not, it's matter what do they point to.
Summary:
1) If you cast a pointer of some type to a pointer of another type, you cannot cast pointer-to-const to pointer-to-non-const.
2) If you have constant pointer, the same rules applies as to other constants - you can assign a constant to a variable but you cannot assign a variable to a constant (except initializing it).
// EDIT
As GMan pointed out, the C++98 standard (§4.2/2) allows to implicitly cast string literals (which are constant char arrays) to a non-const char pointer. This is because of backward compatibility (in C language there are no constants).
Of course such a conversion can lead to mistakes and compilers will violate the rule and show an error. However, GCC in compatibility mode shows only a warning.
conversion from const pointer to pointer
Your addPoint()
takes a non-const pointer:
void Polygon::addPoint(Point* p) {
But you're trying to pass it a const Point*
, hence the error. The compiler doesn't know that you end up not modifying what p
points to - so it could be a violation of const
to let you do what you're trying to do.
For instance, if addPoint()
did:
void Polygon::addPoint(Point* p) { p->setX(42); }
It would be clearly wrong to let you pass a const Point*
in.
However, since you don't actually need p
to point to a non-const Point
you can just change the signature to reflex this:
void Polygon::addPoint(const Point* p) {
Const pointer pointing to non-const data
In this case, there is a type mismatch
No; there is no type mismatch in this case. It is a pointer to non-cost and you initialise it with a pointer to non-const.
Alternatively, if you insist on there being a "mismatch", then it is analogous to the following "mismatch":
const int b = 42;
Why is the second case valid
Simply put: The constness of the initialiser is irrelevant to whether it initialises a const object or not. Besides, the initialiser is a prvalue of a non-class type so const qualification doesn't even apply to it.
C++ - can't assign top-const pointer to another non-const pointer
Emm... Declared type of p1
is int *
. And type of p2
in const int *
.
So you want to assign const int*
to int*
, which isn't allowed. p1 = &var
is allowed, because var
has int
type, not const int
.
assigning a pointer to const to a pointer
A pointer to const
is about privileges, not the fundamental type of the pointed-to object.
Essentially, with an int const *
(which is the same as const int*
), you can look at the int
(which may or may not be const
itself), but you can't change it. Casting a non-const
pointer to a const
one allows you to pass a pointer to your own data to a function and not worry that the function might modify it, even though you still can.
To preserve the above dynamic, you can't "get rid" of const
ness by assigning to another pointer.* That's what your error is saying. That is,
const int * constPtr;
int * nonconstPtr;
*nonconstPtr = 42; // legal
constPtr = nonconstPtr; // legal
*constPtr = 42; // illegal!
nonconstPtr = constPtr; // illegal!
* You actually can cast away const
ness with const_cast<>
. And there are correct uses of the operation. But it is usually very wrong, and you should very probably avoid it.
Why can't I assign value of pointer to const int to a pointer of int?
First consider this example:
void foo(const int* p) {
*x = 1; // Error ! x is pointer to const
}
int x = 42;
foo(&x);
x
is not const
. Nevertheless, inside foo
you are not allowed to modify its value via the const int* p
, because it is a pointer to a const int
. Having a pointer to const int
does not imply that the int
pointed to is actually const
. It only means: You are not allowed to modify the int
via that pointer.
The compiler does not consider what pointer you actually pass to see that *x = 1;
is not allowed inside foo
.
An int *
on the other hand, does allow to modify the pointed to int
. Now consider this:
const int x = 42;
const int* p = &x;
int* p2 = p; // Error ! why?
*p2 = 0; // <- because of this
If you were allowed to assign the const int*
to a int*
this would create a hole in const correctness, because a int*
does allow you to modify the pointee.
The top level const
in
const int* const p3 = &x;
refers to the pointer itself. You cannot modify the pointer. While you can modify this one:
const int* p4;
p4 = &x;
Const pointer to a non-const variable
You told the compiler "I am not going to try assigning to *p
" (that is really all there is to const
), but that says nothing about i
.
#include <stdio.h>
void main(void) {
int i = 1;
const int *p = &i;
printf("i=%d\np*=%d\n", i, p);
i = 5;
printf("i=%d\np*=%d\n", i, p);
*p = 10;
printf("i=%d\np*=%d\n", i, p);
}
GCC will complain about assignment of read-only location '*p'
, but i=5
is fine, since i
is not const
. Remove the const
from *p
, or remove the assignment *p=10
, and everything is good.
If the reference to i
were to somehow disappear, then that memory space would effectively become read-only from the programmer's perspective: the compiler won't let me write to *p
, and that is the only handle I have left for that piece of memory.
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
Related Topics
G++ Error:/Usr/Lib/Rpm/Redhat/Redhat-Hardened-Cc1: No Such File or Directory
Avoid Warning 'Unreferenced Formal Parameter'
Does an Unused Member Variable Take Up Memory
Setting Width in C++ Output Stream
Can You Mix C++ Compiled with Different Versions of the Same Compiler
Cross-Platform Equivalent to Windows Events
Clear Data Inside Text File in C++
Compile Time String Encryption Using Constexpr
C++ Remove_If on a Vector of Objects
How to Store a Lambda Expression as a Field of a Class in C++11
What Optimization Does Move Semantics Provide If We Already Have Rvo
Using Pair as Key in a Map (C++/Stl)
VS 2012 - Project Failed to Build Because of Missing Toolset
Concatenate Compile-Time Strings in a Template at Compile Time