This question already has answers here:
What is the difference between const int*, const int * const, and int const *?
(23 answers)
Closed 6 years ago.
In the code below, why the returned pointer p is allowed to change? If f instead returns "const int *", then the compiler will complain type mis-match error at line "int *p =f()". Why does it do the same for "int * const"?
btw: I know there are memory leaks in the code, but that has nothing to do with the question.
int * const f() {
return new int(23);
}
int main(){
int * p=f();
p= new int(35);
return 0;
}
Because what you are returning is a unmodifiable pointer - not the pointer to unmodifiable data.
Yes, the returned pointer is not modifable - but it will never be modified! You are modifying the different pointer, p - which just happen to have the same value as your unmodifiable (and unnamed) pointer which is now gone - this object is a temporary and forgotten as soon as the statement is completed.
This is why returning const-qualified simple types by value from functions has no sense and actually triggers a warning in some compilers.
*const is a constant pointer while const * is a pointer to constant. The latter is immutable value; you can of course assign this value to a variable, like you would write int x = 42;. The former points at an immutable object, so assigning this to a variable that is supposed to point at a mutable object would presumably violate that object's constness.
In the code below, why the returned pointer p is allowed to change?
Because the type of p is int *. Since the pointer is not const, it may be modified. If you want p to not be modifiable, then you must make it const: int * const p
If f instead returns "const int *", then the compiler will complain type mis-match error at line "int *p =f()"
Pointer-to-const is not convertible to pointer-to-non-const. Such conversion is not allowed by the language because it would break const correctness.
Why does it do the same for "int * const"?
I guess you mean to ask "Why does the compiler allow assigning int * const to a int * variable?"
Copying a const object to a non-const object does not break const-correctness. When p is non-const, it's OK to modify it and the const temporary returned by f remains unmodified through it's entire (short) lifetime.
Constness of a temporary is rarely meaningful, and so is returning a top-level const value.
Related
This question already has answers here:
What is the difference between const int*, const int * const, and int const *?
(23 answers)
pointer-to-const can point to non-const object - language design or technical reason?
(2 answers)
Closed 2 years ago.
Consider the following case 1:
const int n = 5;
int* p = &n;
This is invalid, because &n is of type cont int* and p is of type int * (type mismatch error).
Now, consider this case 2:
int k = 4;
int *const p = &k;
This case compiles successfully, without any error. Clearly, p is of type int * const and &k is of type int *. In this case, there is a type mismatch, but it is valid.
Question : Why is the second case valid, even though there is a type mismatch?
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.
Firstly, int *const does mean a const pointer to a non-const int. So there is absolutely no type mismatching between pointer and pointee types.
Secondly, you can always take the address of a non-const variable into a pointer to a const. So this would be valid too:
int n = 5;
const int * p = &n;
This question already has answers here:
const pointer assign to a pointer
(1 answer)
C++ - can't assign top-const pointer to another non-const pointer
(2 answers)
Assigning const int to a const pointer to int is illegal?
(2 answers)
Closed 2 years ago.
[Note: I saw another question asking about the same section in the same book, but for different reasons]Reading through the C++ primer book and was going through the section "top-level consts". Here it writes that:
The distinction between top-level and low-level matters when we copy an object.
When we copy an object, top-level consts are ignored
When we copy an object,
both objects must have the same low-level const qualification...
This I understood but I went ahead and manipulated an example given in the book multiple times to further my understanding with different scenarios. The code below is one such scenario:
int i = 5;
int *p = &i;
const int *const ptr = p;
p = ptr;
I had hypothesised before I ran the program that, Line 4 would be legal. However, intellisense instead threw me this error:
A value of type "const int *" cannot be assigned to an entity of type "int *"
Now I've done other things like *p = *ptr (which was legal), ptr = p (which would obviously be illegal) and changed the object i to const (which would henceforth require me to change p and satisfy the condition that copying an object must have the same low-level const). And in all cases, I've understood why.
But not for this scenario. Can someone explain why this is illegal?
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;
This question already has answers here:
What is the difference between const int*, const int * const, and int const *?
(23 answers)
Closed 5 years ago.
int p=10;
const int * ptr=&p; // expression 1
As far as i understood by expression 1 that the data which is pointed by pointer ptr is constant
so if i write
*ptr=10;
which is invalid ,
but if i take another pointer variable like
int * pr=&p;
*pr=19;
cout<<*ptr;
will give me the ouput 19
so now the data pointed by ptr changed
but earlier we have seen that data pointed by ptr is constant
why data is changed by another pointer variable?
const int * ptr=&p; means the data pointed to by ptr is const, but only relative to that pointer.
The pointed-to data is not necessarily really const (=originally declared const) and if it isn't, non-const pointers to it (including the original const-pointer cast to its non-const version) may change it.
If some data is really const, attempts to modify it through an non-const pointer result in undefined behavior.
This is very basic, so my suggestion is to read a basic C++ book.
Despite of that I'll provide the answer.
int p = 10;
It is a statement which declares and defines a variable named p of type int.
The content of this variable can be modified. That's because the variable p is not const.
Obviously the later statement p = 13; is still valid and it assigns a new value to that variable.
Now you have this:
const int* ptr = &p;
You're defining a pointer, named ptr which points to that variable.
Adding the qualifier const to the pointer it simply means that you cannot modify the content of the variable by means of the access of the pointer itself.
In other words, the pointer can be only used (for example) for reading the value of p.
On the other hand:
int* pr = &p;
defines a pointer which is not more const qualified.
Indeed, you can access and modify the content of the variable p by means of the usage of that pointer itself. (*pr = 19; is a valid statement).
A little bit far...
This is the general idea behind behind a "more complex world".
The statement:
const int* ptr = &p;
it's possible because the a variable can be implicitly converted in its const version.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
const int = int const?
What is the difference between these combination of keywords ?
const int*
int const*
int* const
Is it possible to modify the value of a constant by accessing its address using a pointer ?
const int*
int const*
Both declare an pointer to an constant type int. It means that the pointer can be made to point to(hold) any other address but any attempt to modify the constant integer data type will result in Undefined Behavior.
int* const
Declares an constant pointer to an int type. It means that the pointer cannot be assigned any new address it will always keep pointing to the same address, but the integer it points to can be changed.
Is it possible to modify the value of a constant by accessing its address using a pointer ?
Yes, it is possible but it leads to a ill formed program exhibiting an Undefined Behavior.
In general:
const T === T const
and
const T * === T const *
but
T * const
makes the pointer constant, but not necessarily the contents of T.
const T * const === T const * const
will make both the contents of T and the pointer itself constants.
As for changing the contents of a const: you shouldn't be able to, but the compiler/OS/CPU don't try too hard to stop you, so you get what is colloquially called “undefined behaviour,” which is a nice way of saying “random crashes on some systems”
const int* and int const* are both a pointer to a constant int. This means that the value pointed to can not be changed but the pointer itself can be.
The third example int *const is a constant pointer to an int. This means that the value can be changed but the pointer can not.
Yes you can change the value of the address by using a pointer but doing so is undefined behavior and should be avoided. C++ also offers a const_cast to remove the constness of a variable.
If you have any other questions related to the const keyword you should reference the const correctness section of the C++ FAQ.
The first two are a variable pointer to a const int. The pointer itself can be changed. Without casting away const, the int can't be changed through this pointer. (It may, however, be modifiable through non-const references.)
The last is a const pointer to a variable int. Without casting away const, the pointer itself can't be changed. The int can be changed through the pointer.
This may be helpful. This is another one that talks about breaking it apart so you can see which parts become const in various scenarios.
Const binds to the left.
Unless it is the left most clause then in binds right.
Just read right to left
const int* => (const int)* => "pointer" to "const int"
=> Pointer can change.
=> Can't change the value it points at (the int is const)
int const* => (int const)* => "pointer" to "const int"
=> As above
int* const => int (* const) => "const pointer" to "int"
=> Can't change the pointer (its const) it always points
=> at the same things.
=> You can change the value of the object it points at.
what does "T const *[]" as parameter
type mean?
What's the difference
compared to "T *[]"?
And as last
question: why can't I pass a "T *[]"
to a function that requires a "T
const * []" as parameter?
Thank you for your help.
Tobias
As a type in general, it's an array of pointers to a constant T.
Try putting a name in it:
T const *x[];
and apply the usual rules: [] binds tighter than *, so it's an
array. Then the * means that its an array of pointers, and
finally, they all point to a constant T. (As usual, const
modifies whatever is to the left of it.)
As a parameter, of course, an array type is converted to
a pointer type, so we end up with a pointer to a pointer to
a constant T. This could also be written:
T const **
If you drop the const, you end up with:
T **
which is not the same thing as T const**.
And the reason you can't pass a T** or a T*[] to the first
form is to prevent things like:
void f(int const* p1[]; int const* p2)
{
p1[0] = *p2;
}
int const x = 10;
int* px[1];
f(px, &x);
*px[0] = 20; // Where does this write?
The fact that the declarations are written using [] is, in this
case, misleading, since the rules for pointers to pointers still
apply.
It's an array of pointers to constant objects of type T (i.e. the pointer can change, but you cannot call a non-const function, or modify a non-mutable data member on these objects). T *[] is an array of pointers to non-const ojects. You can't pass T *[] to a function requiring a T const *[] as it would invalidate the const correctness of the pointers.
See here for more information.