Const before or const after? - c++

To start you probably know that const can be used to make either an object's data or a pointer not modifiable or both.
const Object* obj; // can't change data
Object* const obj; // can't change pointer
const Object* const obj; // can't change data or pointer
However you can also use the syntax:
Object const *obj; // same as const Object* obj;
The only thing that seems to matter is which side of the asterisk you put the const keyword. Personally I prefer to put const on the left of the type to specify it's data is not modifiable as I find it reads better in my left-to-right mindset but which syntax came first?
More importantly why is there two correct ways of specifying const data and in what situation would you prefer or need one over the other if any?
Edit:
So it sounds like this was an arbitrary decision when the standard for how compilers should interpret things was drafted long before I was born. Since const is applied to what is to the left of the keyword (by default?) I guess they figured there was no harm in adding "shortcuts" to apply keywords and type qualifiers in other ways at least until such a time as the declaration changes by parsing a * or & ...
This was the case in C as well then I'm assuming?

why is there two correct ways of specifying const data and in what situation would you prefer or need one over the other if any?
Essentially, the reason that the position of const within specifiers prior to an asterisk does not matter is that the C grammar was defined that way by Kernighan and Ritchie.
The reason they defined the grammar in this way was likely that their C compiler parsed input from left-to-right and finished processing each token as it consumed that. Consuming the * token changes the state of the current declaration to a pointer type. Encountering const after * means the const qualifier is applied to a pointer declaration; encountering it prior to the * means the qualifier is applied to the data pointed to.
Because the semantic meaning does not change if the const qualifier appears before or after the type specifiers, it is accepted either way.
A similar sort of case arises when declaring function pointers, where:
void * function1(void) declares a function which returns void *,
void (* function2)(void) declares a function pointer to a function which returns void.
Again the thing to notice is that the language syntax supports a left-to-right parser.

The rule is:
const applies to the thing left of it. If there is nothing on the left then it applies to the thing right of it.
I prefer using const on the right of the thing to be const just because it is the "original" way const is defined.
But I think this is a very subjective point of view.

I prefer the second syntax. It helps me keep track of 'what' is constant by reading the type declaration from 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 order of the keywords in a declaration isn't all that fixed. There are many alternatives to "the one true order". Like this
int long const long unsigned volatile i = 0;
or should it be
volatile unsigned long long int const i = 0;
??

The first rule is to use whichever format your local coding standards
requires. After that: putting the const in front leads to no end of
confusion when typedefs are involved, e.g.:
typedef int* IntPtr;
const IntPtr p1; // same as int* const p1;
If your coding standard allows typedef's of pointers, then it really
should insist on putting the const after the type. In every case but
when applied to the type, const must follow what it applies to, so
coherence also argues in favor of the const after. But local coding
guidelines trump all of these; the difference isn't normally important
enough to go back and change all of the existing code.

There are historical reasons that either left or right is acceptable. Stroustrup had added const to C++ by 1983, but it didn't make it to C until C89/C90.
In C++ there's a good reason to always use const on the right. You'll be consistent everywhere because const member functions must be declared this way:
int getInt() const;

C uses a right-to-left syntax. Just read the declarations from right to left:
int var = 0;
// one is a pointer to a const int
int const * one = &var;
// two is a pointer to an int const (same as "const int")
const int * two = &var;
// three is a constant pointer to an int
int * const three = &var;
The first thing left to the "const" is affected by it.
For more fun read this guide:
http://cseweb.ucsd.edu/~ricko/rt_lt.rule.html

With
using P_Int = int *;
P_Int const a = nullptr;
int * const b = nullptr;
const P_Int c = nullptr;
const int * d = nullptr;
the variables a and b are the same type as each other but, somewhat confusingly, the variables c and d are not the same type as each other. My preference is for the first scenario, without the confusion: have const on the right of the type. N.B. it is the pointer that is const with a, b, and c; but the int is const with d.

When I work with the existing code, I follow the way already being used which is most of the time, const on left e.g const int a = 10; but if I got a chance to work from start I choose the "right way", means const on right e.g int const a = 10;, which is a more universal approach and straightforward to read.
As mentioned already, the rule is
const applies to the thing left of it. If there is nothing on the left then it applies to the thing right of it.
Here is the example code for basic use cases.
int main() {
int const a = 10; // Constant integer
const int b = 20; // Constant integer (same as above)
int c = 30; // Integer (changeable)
int * const d = &c; // Constant pointer to changeable integer
int const * e = &a; // Changeable pointer to constant integer
int const * const f = &a; // Constant pointer to constant integer
return 0;
}
At the end of the day, if there is no guideline to follow, this is subjective, and harmless to use either approach.

Related

Why does `const` work on the thing immediately preceding it?

I am learning C++. In my course, it is explained that it is best to place const immediately after the thing you want to make unchangeable, because this is how const works.
Many people, including for instance Bjarne Stroustrup himself, like to write const in front. But this sometimes leads to problems:
const int *foo; //modifiable pointer to a constant int.
int const *bar; //constant pointer to a modifiable int? No! It's a modifiable pointer to a constant int. (So the same type as foo)
An example that shows this in action:
int fun(int const *mypointer)
{
*mypointer = 5; //Won't compile, because constant int.
mypointer = 0; // Is okay, because modifiable pointer.
}
What makes this even more confusing, is that compilers such as g++ like to rewrite int const bar to const int bar in their error messages.
Now, this behaviour is confusing me greatly. Why does const work in this way? It would seem a lot easier to understand if it would 'just' work on the thing put after it.
C++ follows syntax of C.
It looks weird, but in C you specify not a type of variable, but a type of expression with it:
int v means that v is int;
int *v means that *v is int, so v is pointer to int;
int v[] means that v[…] is int, so v is array of int;
int v() means that v() is int, so v is function returning int;
etc (you always need to read such declaration from inner).
More closely to your question, in C type specification can consist of several words: unsigned char, long int, const double (even more than two — const unsigned long long int). Number of repeated words matters (long long int in general case is different from long int), but order of words doesn't (long int is the same as int long). That's why const int *p is the same as int const *p (as well as const int i is the same as int const i).
As for int * const p, it probably doesn't obey common scheme. As there is no such expression as * const p (where p is a variable) in C, so we can't explain it with something like "expression * const p will have type int". However, think, where else can we put const keyword to specify that pointer itself is constant, not its dereferenced value? (Assuming that both const int *p and int const *p mean that a dereferenced value is constant, and we don't want to introduce additional keywords into language.) Nowhere except after *; so here it goes.
To understand a C declaration there is a Right-Left rule that is very helpful: For example
int *
is a pointer to an integer (note that you have to read that right to left). Same thing for reference to int:
int &
Now read the type of p8 from right to left:
char * const * const p8; // const pointer to const pointer to char
I suspect that const modifies the preceding type, just to be consistent with that rule. The fact that you can put const in the very beginning of the declaration is an exception.
Note: the example comes from this article (but I changed it slightly).

C/C++ convention for pointers and `const`

I have read this (Pasted below as well) on Wikipedia:
Following usual C convention for declarations, declaration follows use, and the * in a pointer is written on the pointer, indicating dereferencing. For example, in the declaration int *ptr, the dereferenced form *ptr is an int, while the reference form ptr is a pointer to an int. Thus const modifies the name to its right. The C++ convention is instead to associate the * with the type, as in int* ptr, and read the const as modifying the type to the left. int const * ptrToConst can thus be read as "*ptrToConst is a int const" (the value is constant), or "ptrToConst is a int const *" (the pointer is a pointer to a constant integer).
I really am not able to get a satisfying interpretation:
In which sense does it modify?
What is intended with name vs type (see the above link)?
And why should it be on the right side of const?
The const, volatile and restrict (C99 onwards) keywords are considered type qualifiers. They are an integral part of type signatures and describe additional semantics about a type.
If they appear at the topmost level of a declaration, they affect the declared identifier:
const int a = 5; // prevents modifications of "a"
int *const p = &x; // prevents modifications of "p", but not "*p"
int **const q = &y; // prevents modifications of "q", but not "*q" and "**q"
If they appear in pointer subtypes (before an asterisk), they affect the pointed-to value at the particular level of dereferencing:
const int *p = &x; // prevents modifications of "*p", but not "p"
const int **q = &y; // prevents modifications of "**q", but not "*q" and "q"
const int *const *r = &z; // prevents modifications of "**r" and "*r", but not "r"
const int *const *const s = &a; // prevents modifications of "**s", "*s" and "s"
The Wikipedia excerpt discusses two different conventions for declaring pointers:
int *p; // more common in C programming
int* p; // more common in C++ programming
I would say that the "true" convention is the first one because it works according to the syntax of the language (declarations mirror use). The asterisk in that declaration is in fact the same dereferencing operator that you would use on the pointer in normal expressions. Thus the int type is returned after applying * (indirection) on p (the pointer itself).
Also note that the ordering of type qualifiers with respect to type specifiers and other type qualifiers does not matter, so these declarations are equivalent:
const int a; // preferred
int const a; // same, not preferred
const volatile int b; // preferred
volatile const int b; // same, not preferred
volatile int const b; // same, not preferred
const int *p; // preferred
int const *p; // same, not preferred
In which sense does it modify?
Modifies in the sense that it makes it constant, meaning it can't be modifed (assigned to, or passed to a function which might modify it).
What is intended with name vs type (see the above link)?
Name means the word written in the source code here, I think.
And why should it be on the right side of const?
"Modifies name to its right" means, by example:
const char * str, here const modifies char, in other words the characters are constant, you can't modify them. You can make str point to a new char, but you still can't modify it either (at least not through str). *str = 'a'; is compiler error, str = "foo"; is ok.
char * const str, here const modifies str, in other words the value of str can't be modified. It points to some char, and you can modify that char through str, but you can't make str to point to another char. *str = 'a'; is now ok, str = "foo"; is error.

C++ pointer to constant error

In a book I'm reading about C++ (C++ for Dummies) there is a section that says the following:
int nVar = 10;
int* pVar = &nVar;
const int* pcVar = pVar; // this is legal
int* pVar2 = pcVar; // this is not
The book then goes on to explain:
The assignment pcVar = pVar; is okay -- this is adding the const
restriction. The final assignment in the snippet is not allowed since
it attempts to remove the const-ness of pcVar
My question is why is the last line not "legal". I don't understand how that impedes on the "const-ness" of pcVar. Thanks.
const int *pcVar = pVar;
int *pVar2 = pcVar;
If pcVar is const int *, that implies that the int it points to may be const. (It isn't in this case, but it may be.) So if you assign pVar2, which is a non-const int *, it still allows the int it points to to be modified.
So if pcVar actually pointed to a const int, and you assign an int * to its address, then that int * pointer (pVar2 in this case) will allow you, by dereferencing, to modify it, and that's illegal (it's a constraint violation, so it invokes undefined behavior).
All the compiler knows is that pcVar is a const int*. That is, it points to a const int. Just because you made it point at a non-const int doesn't matter. For all the compiler knows, the pointer value could have changed at some point to point at a truly const int. Therefore, the compiler won't let you convert from a const int* back to a int* because it would be lying about the constness of the object it was pointing at.
For a simpler example, consider:
const int x;
const int* pc = x;
int* p = pc; // Illegal
Here, x truly is a const int. If you could do that third line, you could then access the const int object through p (by doing *pc) and modify it. That would be bad - x is const for a reason.
However, in the example you gave, since you know that the original object was non-const, you could use const_cast to force the compiler into trusting you:
int* pVar2 = const_cast<int*>(pcVar);
Note that this is only valid if you know for certain that the object is non-const.
It's just saying you can't create a non-const pointer from one that was const (at least, not without a const_cast).
The idea behind const is to have objects that cannot be modified by accident. Getting rid of const through a simple assignment would be quite dangerous, and would allow things like this:
void function(int* m) {
*m = 20;
}
int main() {
const int x = 10;
//Oops! x isn't constant inside function any more, and is now 20!
function(&x);
}
Also, please check out The Definitive C++ Book and Guide List, it has lots of great references (C++ for dummies doesn't quite make the cut).
Mixing const and non-const is illegal. The reason being, if you tell the compiler that one location's value is const and then use another pointer to modify that value, you have violated the const contract you made with the first element.
pcVar stays the same but pVar2 points to a non-const, const can be added but not taken away. The compiler does not look at the original nVar being non-const, only the attempt to assign a const to a non const. Otherwise you could get around the const and change the value.
int * pVar = &nVar;
*pVar = 4 //is legal
const int* pcVar = pVar; // this is legal
*pcVar = 3 // this is not legal, we said the value was const thus it can not be changed
int* pVar2 = pcVar; // this is not legal because...
*pVar2 = 3 -> *pcVar = 3
The second line
int pVar = &nVar;
is error.
g++ compiler says.
error: invalid conversion from ‘int*’ to ‘int’

pointer and ampersand position with const in C++ [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Declaring pointers; asterisk on the left or right of the space between the type and name?
I've always been wondering what's the exact correct position to put * and &. it seems that C++ is pretty tolerant about where to put these marks.
For example I've seem pointer and ampersand been put on both left and right of a keyword or in the middle of two keywords, but confusingly sometimes they seems to mean the same thing, especially when used together with const
void f1(structure_type const& parameter)
void f2(structure_type const &parameter)
void f2(structure_type const *sptr);
void f2(structure_type const* sptr);
void f2(structure_type const * sptr);
The examples are not exhaustive. I see them everywhere while being declared or been passed to a function. Do they even mean the same thing? But I also see cases while putting * will affect which object being referred as a pointer (likely the case where * is in between two keywords).
EDITED:
int const *Constant
int const * Constant // this above two seem the same to me, both as pointer to a constant value
int const* Constant // EDIT: this one seems the same as above. instead of a constant pointer
const int * Constant // this is also a pointer to a constant value, but the word order changed while the pointer position stays the same, rather confusing.
int* const Constant
int * const Constant // instead, these two are constant pointers
So I concluded this:
T const* p; // pointer to const T
const T* p // seems same from above
T* const p; // const pointer to T
Still, this confused the hell out of me. Doesn't the compiler care about position and the spacing required for them?
Edit:
I want to know in general of the position matters. If yes in what cases.
White space matters only to the degree that it keeps tokens from running together and (for example) creating a single token, so (for example) int x is obviously different from intx.
When you're dealing with something like: int const*x;, whitespace on either size of the * makes absolutely no difference to the compiler at all.
The difference between a pointer to const int and const pointer to int depends on which side of the * the const is on.
int const *x; // pointer to const int
int *const x; // const pointer to int
The primary difference is readability when/if you define/declare multiple objects in the same declaration.
int* x, y;
int *x, y;
In the first, somebody might think that x and y are pointers to int -- but in fact, x is a pointer to an int, and y is an int. To some people's eyes, the second reflects that fact more accurately.
One way to prevent any misinterpretation is to only ever define one object at a time:
int *x;
int y;
For any of these, correct interpretation is fairly easy if you ignore whitespace entirely (except to tell you where one toke ends and another starts, so you know "const int" is two tokens) and read from right to left, reading * as "pointer to". For example: int volatile * const x; is read as "x is a const pointer to a volatile int".
int const *Constant
int const * Constant
int const* Constant
All of the above intend to declare a non constant pointer to a constant integer.
Simple rule:
If const follows after the * it applies to the pointer if not it applies to the pointed object. The spacing doesn't matter.
Both & and * placements in variable declaration are acceptable and only depends on your own flavour. They strictly mean the same thing, creating respectively a pointer and a reference.
However, the const keyword placement is primordial, as a int const* variable declares a constant pointer to a non-constant int, and const int* variable is a non-constant pointer to a constant int.

C++ Const pointer declaration

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.