I was reading a C++ template example, and part of the template signature confused me.
Am I reading this correctly:
const T* const foo;
Is foo a const* to a const T?
Yes, it's a constant pointer to a constant T. I.e., you can neither modify the pointer, nor the thing it points to.
const T* would only forbid you to modify anything the pointer points to, but it allows you (within the bounds of the language) to inspect the value at *(foo+1) and *(foo-1). Use this form when you're passing pointers to immutable arrays (such as a C string you're only supposed to read).
T * const would mean you can modify the T value pointed to by foo, but you cannot modify the pointer itself; so you can't say foo++; (*foo)++ because the first statement would increment (modify) the pointer.
T * would give you full freedom: you get a pointer into an array, and you can inspect and modify any member of that array.
Yes; that is exactly what it means.
Since there is always a little confusion about const when using pointers, there are the following possibilities:
const T * aConstant
means aConstant is a variable pointer to a constant T.
T const * aConstant
does exactly the same.
T * const aConstant
declares that aConstant is a constant pointer to a variable T and.
T const * const aConstant (or const T * const aConstant)
declares a constant pointer to a constant T.
This is a const pointer-to-const T. So if T was an int, then array is a pointer to an int that is const in two ways:
pointer-to-const: the value that the pointer is pointing to cannot be changed (or pointing to const int)
const pointer: the memory address stored in the pointer cannot change
This is also the same as T const * const array
See wiki on const correctness.
Yes, foo is a constant pointer to constant T.
Yes.
const T*
makes the elements of the array const... at least, as far as foo is concerned.
foo[0] = T(); // Illegal!
foo[1] = T(); // Illegal!
foo[2] = whatever; // Illegal!
const
makes foo a constant pointer. Therefore, this is illegal:
foo = &some_array;
The variable
foo
...if you don't know what this is, you should seriously consider going to preschool.
Yes it is, i think name of var(const) is what stumbles you.
Yes, it just simply means that not only can't you change what foo points to, but you also can't change the value of foo itself so that it points to some other T instance.
simply parse it like this
const<ptr<const<T>>> foo
although it is illegal, but I think everyone can grasp its essence.
Related
From what I understood about using the const type qualifier with a pointer, is that it depends where you use it.
const MyType *
Would mean that the location cannot be modified, but the value at the location can.
MyType const *
Would mean that the location can be modified, but not the value at the location.
From this, I would seen no reason for the following not to be valid,
const MyType const *
To define a pointer whose location is fixed, and for which the value pointed to cannot be modified. However, this is throwing "same type qualifier used more than once." Should I ignore this? Is my understanding of const semantics in the context of pointers flawed?
You are slightly mistaken about the syntax. In fact
const MyType *
and
MyType const *
mean the same thing: the underlying MyType object is constant. The syntax for making the pointer itself constant is:
MyType * const
Thus if you want both to be constant, you would use:
MyType const * const
Or:
const MyType * const
A way to remember this is: the thing which is constant is the thing immediately to the left of the keyword const (which is * for pointer or MyType for the object), unless there is nothing to the left: in which case it is the thing to the right.
const MyType * and MyType const * are the same thing. They both mean pointer to const, i.e. the pointee is const. So for const MyType const *, you'll get the error because the const qualifier is used twice for the same thing.
What you want might be MyType const * const(note the position of const and *), which is a const pointer to const, i.e. the pointer itself and the pointee are both const. You could read it from right to left as "const pointer to const MyType".
I have written following 3 functions in C++. Kindly explain me how all return types are different? And how the return values will be stored in Memory? I know const keyword applies to whatever is on immediate left but i need more explanation.
const int* sample1();
int* const sample2();
int const* sample3();
const int* sample1();
int const* sample3();
These functions are identical. They return pointer to constant memory (this memory cannot be changed via this pointer). But we can change pointer itself. Increment it for example.
int* const sample2();
This function returns constant pointer to non-constant memory. We cannot change pointer itself, but we can change the memory it is point.
const does not have to apply to whatever is on immediate right. For example
class Foo
{
void Bar() const;
int var;
}
This will will ban the function Bar in Foo to alter any member variables in the object.
Besides this us2012's comment sums it all up.
I might be totally of but this seems like a school assignment or something?
I am reviewing some code and I ran across some code I am unfamiliar with. After some searching I could not come up of any example of why this is done or the benefit of this declaration.
myClass const * const myPtr = myClass->getPointer();
Is this a declaration of a const pointer or something entirely different?
It means "myPtr is a const pointer to a const myClass". It means that you can neither modify what the pointer is pointing at through this pointer nor can you make the pointer point somewhere else after it's initialised (by the return value of myClass->getPointer()). So yes, you're basically right, with the addition that it also points to a const object (as far as you know; it could really be non-const underneath).
Remember that const applies to the item to its left (or if there is no item to its left, the item to its right). The first const makes the myClass const (where you can't modify what the pointer points at) and the second const makes the * const (where you can't modify the pointer itself).
In some cases, you may see it written like this:
const myClass * const myPtr = myClass->getPointer();
The two are equivalent, namely a constant pointer to a constant object. I prefer the syntax as you've shown it because it is easier to understand for newbies when read right-to-left:
Object * const obj; // read right-to-left: const pointer to Object
Object const * obj; // read right-to-left: pointer to const Object
Object const * const obj; // read right-to-left: const pointer to const Object
The rule is that the const keyword applies to the "word" on the left of it, unless it's the first word on the line, in which case it applies to the "word" on the right of it. So: myClass const * const: myClass <- const, pointer <- const, const pointer to const myClass.
For some reason, in most code (at least the one I've seen), this would be declared as const myClass * const. Why I have no clue, because now you have to take the exception to the "const applies to word on the left, unless it's first word on the line" into account. I.e.: writing lines they way is done in the code you are reviewing is a lot clearer.
This declares a constant pointer to a constant value, returned by calling the member function of a dereference pointer myClass
Seth is on the money. There's some more background you might find useful on Duramecho as well.
The first const is a valid use while the second const is superfluous IMO.
When you use
myClass const * const myPtr = myClass->getPointer();
You cannot change the object that myPtr points to.
You cannot change where myPtr points to either.
myPtr->SomeMember = SomeValue; // Not allowed. That's OK.
// The state of myClass is protected.
myPtr = nullptr; // That's not allowed either.
// I don't think it is necessary to disallow this.
You should be able to use
myClass const * myPtr = myClass->getPointer();
without any harm.
For example:
I could make a constant pointer, which points to an object that I can change through my pointer. The pointer cannot be reassigned:
MyObj const *ptrObj = MyObj2
Why would I use this over:
MyObj &ptrObj = MyObj2
What you have there isn't a const pointer, it's a pointer to a const object - that is, the pointer can be changed but the object can't. A const pointer would be:
MyObj *const ptrObj = &MyObj2;
As to why you might prefer it over a reference, you might want the flexibility of using the NULL special value for something - you don't get that with a reference.
You got it wrong. What you have is a mutable pointer to a constant object:
T const * p;
p = 0; // OK, p isn't const
p->mutate(); // Error! *p is const
T const & r = *p; // "same thing"
What you really want is a constant pointer to mutable object:
T * const p = &x; // OK, cannot change p
T & r = x; // "same thing"
p->mutate(); // OK, *p is mutable
Indeed, references are morally equivalent to constant pointers, i.e. T & vs T * const, and the constant version T const & vs T const * const.
If you insist on getting some advice, then I'd say, "don't use pointers".
The important difference between a pointer and a reference is how many objects they may refer to. A reference always refers to exactly one object. A pointer may refer to zero (when the pointer is null), one (when the pointer was assigned the location of a single object) or n objects (when the pointer was assigned to some point inside an array).
The ability of pointers to refer to 0 to n objects means that a pointer is more flexible in what it can represent. When the extra flexibility of a pointer is not necessary it is generally better to use a reference. That way someone reading your code doesn't have to work out whether the pointer refers to zero, one or n objects.
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.