I tried to search answer for this but I found it very hard to find 'exact' example of this kind. I understand very little about pointers to pointers and I feel there is something more laying under the skin of this than just pointer to something.
So how would you guys translate this?
void free(shame_1 * const * const group_1);
Am I right if I translate it as const group_1 pointer to const pointer to shame_1?
Thanks.
shame_1 * const * const group_1;
declares a variable named group_1, whose type is a const pointer (you cannot change where it points at) to another const pointer (same) to a shame_1-type object, whose value you can actually change.
So, for instance, you cannot compile:
group_1 = nullptr;
*group_1 = nullptr;
You can, however, do:
void f(shame_1& group) {
//stuff that modifies group
...
}
f(**group1);
As zakinster commented, having a look at the spiral rule should help you understand this kind of notation.
Generally, just read from right to left:
void free(shame_1 * const * const group_1);
free takes a parameter called group_1 that's a const pointer to a const pointer to a shame_1 object.
It's not relevant here, but the main hassle reading right-to-left is that some people use T const * and others use const T* and they mean the same thing, so whether you see either T const or const T you should read it as const T. In your code, only the pointers are const anyway.
For example:
shame_1 a_shame;
const shame_1* p_a_shame = &a_shame;
free(&p_a_shame);
There's very little utility in this... free() could have accepted a const pointer to a shame_1 without an extra level of indirection, and would still have been able to do all the same things to the shame_1, so it's only useful if free() has to pass the const-pointer-to-const-pointer to some other function (with ultimately there being no good reason for the whole mess).
You can visualise the memory usage / relationships as:
[a_shame] <------ [p_a_shame] <------ [group_1]*
this is likely only in a CPU register, though the others may be too after optimisation.
Am I right if I translate it as const group_1 pointer to const pointer to shame_1?
So, to me the "const group_1 pointer" bit is a bit suspect... I think it reads better as "group_1 is a const pointer to..." or "const pointer (called group_1) to...".
Related
I understand the concept of final in Java or const in C++ for forcing constant values and allowing the compiler to enforce that on anyone using the modules you write.
I am not able to see where would you want to have a const pointer, why would you not want the pointer to change regardless of the data being constant or not:
e.g
why this?
char greetings[] = "Hello";
char * const p = greetings; // const pointer, non-const data
const char * const p = greetings; // const pointer and const data
I cannot visualize an exmaple where you want to keep the pointer const, could it be for a file handle or something similar? or just a pointer to an object you don't want to change?
You may want to make a pointer itself constant for several reasons:
Helping others understand your code - When you declare a pointer and make it constant, you tell the readers that there are no changes done to that pointer in the rest of your function, so they would have a better idea of how you use the pointer.
Helping others maintain your code - Someone else who maintains your code after you will have better idea of what you expected to do with the pointer. If he tries to pass a non-constant reference or a pointer to the pointer that you declared const, the compiler is going to catch this error.
Enable compiler optimizations - When compilers see something declared const, they can optimize more aggressively.
Apologies for this, I am a student trying to learn C++ and I just thought it'd be better to ask than to not know.
I understand what the "address of" operator & and the const keyword mean separately. But when I was reading some sample code I saw const&, and I just wanted to know what it means.
It was used in place of an argument in a function prototype, for example:
void function (type_Name const&);
If only one of them were used I would understand but I am a little confused here, so some professional insight would be great.
Types in C++ are read right to left. This is, inconveniently just the opposite direction we like to read the individual words. However, when trying to decide what qualifiers like const or volatile apply to, putting the qualify always to the right make it easier to read types. For example:
int* const is a const pointer to a [non-const] int
int const* is a [non-const] pointer to a const int
int const* const is a const pointer to a const int
For whatever unfortunate accident in history, however, it was found reasonable to also allow the top-level const to be written on the left, i.e., const int and int const are absolutely equivalent. Of course, despite the obvious correct placement of const on the right of a type, making it easy to read the type as well as having a consistent placement, many people feel that the top-level const should be written on the left.
In this context, & is not an address-of operator.
void function (type_Name const&);
is equivalent to:
void function (const type_Name &);
which is nothing but prototype of function taking argument by const reference. You should study this kind of topics on your own, ideally from some good book. However, if you're looking for some additional material, these questions might help you too:
What are the differences between a pointer variable and a reference variable in C++?
Pointer vs. Reference, When to use references vs. pointers, Pass by Reference / Value in C++
I want to insert some elements to the list.
What I really want to do is to use "insert3" because it guarantee that the pointer won't change, and the data won't change.
But "insert2" and "insert3" give the following error, which "insert1" doesn't:
class A
{
public:
std::list<int*> l;
void insert(int* const a)
{
l.push_back(a); //works
}
void insert2(const int* a)
{
l.push_back(a);
/*
no instance of overloaded function "std::list<_Ty, _Ax>::push_back [with _Ty=int *, _Ax=std::allocator<int *>]"
matches the argument list
*/
}
void insert3(const int* const a)
{
l.push_back(a);
}
};
Thanks for your help!
Short answer
You should use a list<int const* const> as the type of l instead and then you can use any of your inserts including insert3.
Long answer
By inserting into a list<int*> you attempt to convert your int const* (pointer to const int) to an int* (pointer to int).
Since you are removing the guarantee that you will not edit the target of the pointer, this is not implicitly doable. You may use a const_cast (or c-cast) if you really wish to do this, but usually casting away const-ness is a very bad idea (tm).
Why making the pointer itself const won't change a thing
If you use version 3 using an int const* const (const pointer to const int), you are not getting anything more or less than the guarantee that the variable a will not be changed while insert3 is running. By inserting the pointer into your list, you are actually copying it. This means that no matter whether a is const or not, your resulting list item will be the type you specified in the beginning.
By making the list into list<int const* const> you ensure that any pointer inserted cannot be changed later on, and the value pointed to it can only be changed after explicitly getting rid of the constness of your pointer. Inserting into it is possible, since adding const is always implicitly possible
Change the list to take a pointer to const:
std::list<const int*> l;
Since you had a pointer to const for the parameter, taking away its const-ness through an implicit conversion wouldn't be allowed.
It is one of the typical higher-level "issues" with C++-style compile-time const-correctness type system.
If you want to store int * pointers in your list, then you will not be able to add const int * pointers to that list (for obvious reasons). This will allso force all your insert methods to accept int * pointers, not const int * pointers.
I understand, that what you really want to express is that insert method itself does not change the pointed data (and it doesn't). However, as you can see, insert has some far-reaching side-effects - it stores the pointer in a list. This would potentially violate the const-correctenss if insert accepted const int * pointers.
In other words, it is not enough to consider what insert is doing by itself, it is also important to consider what possibilities insert opens to other code (in this case - to other code that has access to the same list). And in your case the possibilities it opens would easily allow const-correcness violations in other code if your insert quietly accepted const int * pointers.
You can, of course, impose your own vision of proper const-correctness in this case by using forceful const_casts. But it won't look pretty.
I have two pointers (const Vec* a and const Vec b)
in a given piece of code, I need to pass these two values, which are instantiated during the code, for a function that has no parameter (const Vec *) but only (Vec *).
How could I do this without moving the function definition, but if necessary, what procedure should I take?
//const Vec* from;
//const Vec* at;
Vec* viewVec;
viewVec = Vec::sub( view->at, view->from);
//static Vec* sub(Vec*, Vec*);
Vec* Vec::sub(Vec* a, Vec* b) {
return new Vec(a->x - b->x, a->y - b->y, a->z - b->z);
}
The simplest answer is probably: "don't". If you need to use a Vec * instead of a Vec const *, then declare it that way to begin with.
If this is some third party function that promises not to modify it but for some reason has an aversion to const, then the const_cast solutions that other people listed is your only choice (other than to use a better third-party library).
If the std::vector that the pointer you have points to is actually not const (at its point of declaration), and you just happen to have a std::vector const * that refers to it, then it's 'safe' (but still generally unwise) to use const_cast on it. However, if you modify any variable that was originally declared as being const, then it is undefined behavior. For instance, the compiler may see that you are doing some expensive operation on a std::vector const multiple times, and it's free to cache certain parts of the result because it can assume that it's always dealing with the same thing, so if you change it, you may get incorrect (or even inconsistent) results.
You can use const_cast for this, e.g.
viewVec = Vec::sub(const_cast<Vec*>(view->at), const_cast<Vec*>(view->from));
Whether or not you should is another matter. If you really can't change the signature of the function (which is probably the easiest fix), you can always write a wrapper which contains the dodgy casting - that way, at least the caller doesn't need to do any casting itself:
Vec *Vec::sub(const Vec *a, const Vec *b) {
return sub(const_cast<Vec*>(view->at), const_cast<Vec*>(view->from));
}
const_cast<type>(value) There ya go ;)
As people have mentioned you could use const_cast. The reason you have to be careful doing this is that you might end up modifying something that shouldn't be modified. For exampl, if some object declares a pointer as const it is because it wants to ensure that this pointer cannot change. If you then const_cast the pointer and pass it to another function, the other function could make it point at something new, hence screwing with the original object which tried to protect it.
In particular, what if object A allocated some piece of memory which the const pointer points to. If you then pass the pointer to a function via const_cast and this function deletes the memory, or re-allocs it, then the original piece of memory will exist undeleted.
Hope this helps.
I am trying to learn C++ via some web tutorials. I don't have a compiler available to me, otherwise I would try this out. I'm not sure what is meant by a const pointer. Does that just mean it always points to the same memory address? Why would you ever want to do that? Would the following code be legal?
...
int * const aPointer = new int;
... //do something with aPointer
delete aPointer;
... //do something else, including possibly more 'new' statements
aPointer = new int;
...
A simple way to remember how const works with pointers is to remember that it always applies to whatever is to the left of it, unless it's the left-most keyword, in which case it applies to the right.
Examples:
Pointer to a constant char:
The pointer can be changed to point to something else, but the char it initally points to cannot change value.
const char * p;
Constant pointer to a char:
The pointer cannot be changed to point to anything else, but the char it points to can change value.
char *const p;
Constant pointer to a constant char:
The pointer cannot be changed to point to anything else, and the char it points to cannot change value.
const char *const p;
Const pointer could mean a few different things. I recommend checking out the C++ FAQ Lite on the matter.
You can have:
const int* p;
int* const p;
const int* const p;
All three mean different things. Yes, it's kind of confusing.
In your case, you have the second, which means you have a constant pointer to a non-constant object. That is, you can change the value of the integer via the pointer, but you can't change what the pointer points to. So the code you posted would not be legal.
You can't learn to drive a car just by reading books.
Get yourself a C++ compiler if you want to learn C++. g++ is free of charge, as well as Visual Studio 2008 Express Edition.
As for your question, a const pointer is a zone of memory that is ready only. Example: A class may provide read-only access to an internal buffer.
Note that you also have the const pointer that is also const, aka
const char * const p
In that case, even the value of the pointer cannot be modified.
G'day,
To remember this easily you can use the trick that Scott Meyers describes in his excellent book "Effective C++" (sanitised Amazon link)
You draw a line through the declaration where the asterisk is located.
If the keyword const appears to the left of the line, then you can't change the value of the item that you're pointing to.
If the keyword const appears to the right of the line, then you can't change the pointer to point to another location.
If const appears on both sides, then you can't change the pointer and you can't change the value of what you're pointing to.
BTW That book is excellent, and while not for a beginner, is definitely a way of taking your C++ knowledge to the next level! Highly recommended.
HTH
cheers,
A const pointer means that you can change the value of the variable which is being pointed to, but you can't change where the pointer is pointed. I don't use them often myself, but a common application for const pointers is in defining specific memory segments that you need to address. See this question for more information.
As an aside, you should try to get a compiler on your computer if you can. I've shown myself many times that human brains are poor C++ compilers.
Your code is not legal. You can't assign to aPointer (except using copy-style initialisation, which in fact is not assignment even though it looks like it) if aPointer is declared const like that.
But usually when people say "a const pointer", they mean const int * aPointer, not int * const aPointer as you have in your code. The whole internet will explain the difference at the drop of a hat. As far as I know, the term "const pointer" isn't defined in the standard, so we're free to do this even though it's potentially confusing. "Pointer-to-const" would be an unambiguous description, and a pointer-to-const is much more commonly used than a pointer-which-is-itself-const.
A pointer-which-is-itself-const is used to refer to something, where you won't want the pointer to refer to a different thing at any point in its life. For instance, this is a pointer-which-is-itself-const, because "this object" remains the same object through the execution of a member function. The C++ language has opted not to let you decide part way through that you want to assign some other value to this, to make it refer to some other object. In C++ references often serve that purpose too, since they cannot be "re-seated" to change the referand.
In your code, the pointer cannot move, but the data pointed to can change.
It's legal up to the first delete. A subsequent new would not work because it's an assignment to a constant.
It's relatively unusual to see this, more common is to see where the data pointed to is unchangeable but the pointer can move.
int bar;
int baz;
const int * foo = &bar;
*foo = 4; // illegal
foo = &baz; // legal
having both pointer and value being const is common with strings
const wchar_t * const myString = L"String that will never change.";
Since you're new to C++, for the answer to this question and many other questions you may have or don't know you have, check out the C++ FAQ
I don't have a compiler available to me, otherwise I would try this out
Everyone has a C++ Compiler available to them: http://www.online-compiler.com
There are many others, but this seems to work...
As it has already been pointed out the perhaps most common const pointer is
const char* p;
The variable p can change, but the data p points to is unmodifable.
However, moving the const keyword to the left of the asterisk does not alter the meaning of the declaration:
char const* p;
I prefer the later since it becomes much easier to remember where to place the const keywords when declaring const pointers to const pointers:
char const* const* p;
Again, the variable p can change and the data pointed to is unmodifiable. Furthermore, the data is declared as const pointers meaning that it points to data that cannot be modified.
The more common notation for this type is
const char* const* p;
Placing the const keyword immediately to the left of the asterisk it modifies (or ampersand for reference) makes it easy to create complex types involving the const keyword. For example, a pointer to const pointers:
char const** p;
and a const pointer to pointers:
char* const* p;
Remember to "read" pointer declarations from the right to the left, and don't declare more than one pointer in each statement to avoid a lot of confusion.