C++ constructor with a const argument - c++

I just wondered what's the difference between having a constructor with const char* c or char* const c as a parameter?
If I swap char* and const in header and source file it isn't a problem but when I mix them it won't compile, saying there is no such overloaded constructor.
When I use my own class for a copy constructor the compiler doesn't seem to bother if I have MyClass const &other and const MyClass &other mixed..
Can anyone enlighten me please? :)

This record const char *c declares pointer c that points to an object of type const char. That is using this pointer you may not change the object that refered to by the pointer.
This record char * const c declares const pointer c that points to a non-const object of type char. You may not change the pointer itself but you may change the object refered to by the pointer.
There is a difference between declaring pointers and references. Though there is used term "constant reference" strictly speaking references themselves may not be constant. According to the C++ grammar
ptr-operator:
* attribute-specifier-seqopt cv-qualifier-seq
& attribute-specifier-seqopt
references do not contain cv-qualifier-seq. So for example this record
Airplane & const other
will be incorrect and the compiler shall issue an error.
As for these records
const Airplane & other
Airplane const & other
then they are equivalent the same way as equivalent the recirds below
const char *c
char const *c

Think of the * as a "fence". What's before it in the declaration defines the type that the pointer refers to. What's after the * defines the pointer itself. For this case, it's easiest to read things backwards (translating * as "pointer to"), so char const *t is read (from back to front) as: "t is a pointer to a const char". Likewise, char *const t is read as: "t is a const pointer to a char."
char *const means the pointer itself is const (can't be modified), but the char(s) it points at can be modified.
char const * or const char * are equivalent to each other. Both mean the pointer itself can be modified, but what it points at cannot.
Substituting a different type for char doesn't change that basic idea.
The same is true with a reference: const T & means a reference to a const T, so you can't modify the T that it refers to. In the case of a reference, you can't modify the reference itself to refer to a different object, so T & const doesn't make any real sense (and isn't allowed).

const applies to the type to its left (or to its right if there is nothing on its left), so const char * and char const * are the same and mean that the characters cannot change, but the pointer can, whereas char * const means that the characters can change but the pointer cannot

The order in which const and char* are written actually make a difference. If you have const char* in your header but char* const in your source file, you will get an error because the compiler won't regard these as the same.
const char* p means that p points to a char that is constant. We can alter where p points to, but we can never alter the contents stored at p.
char* const p means that p is a constant pointer and is pointing to a char. We can alter the contents stored at p, but we cannot alter where p points to.
const char* const p means that p is a constant pointer to a constant char. We cannot alter where p points to nor can we alter the contents at p. Hope this is helpful!

Related

My pointers are causing "same type qualifier used more than once" warnings?

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".

Difference between const ref and const pointer, c++

I'd like to know what's the difference between const ref and const pointer in c++.
When I declare on something to be const ref, can I change it's VALUE?
or the const goes on the object?
Because I know that const pointer means you cannot change the POINTER but you can change the VALUE it points to.
for example:
const char& a; // ?
const char* a; // pointer is const
Fred const& x;
It means x aliases a Fred object, but x can't be used to change that Fred object.
Fred const* p;
Fred const* p means "p points to a constant Fred": the Fred object can't be changed via p.
Fred* const p;
Fred* const p means "p is a const pointer to a Fred": you can't change the pointer p, but you can change the Fred object via p.
It's possible to combine the last to to get:
Fred const* const p;
Fred const* const p means "p is a constant pointer to a constant Fred": you can't change the pointer p itself, nor can you change the Fred object via p.
For more on this visit this link.
const char* a; // pointer is const
Wrong, this is a pointer to a constant. This:
char* const a; // pointer is const
is a constant pointer.
I prefer to write these like this: char const * a vs. char * const a.
This allows you to read from right to left: char const * a is: a is a pointer to a constant char, and char * const a is: a is a constant pointer to a char. And if I read other code, I just remember that const char* a = char const* a.
To answer the other part of your question:
When I declare on something to be const ref, can I change it's VALUE?
People misuse the term const ref to actually mean reference to a constant (since a constant reference makes no sense). So, const ref const char& a means that you cannot change the value. But if you actually mean you want a constant reference, char& const a then you can change the value and the const part makes no difference.
For pointers, const char* a means you cannot change the value a points to. Compare this to char* const a which means you cannot change the pointer, but you can change the value a points to.

const - Shouldn't it not change

In running this C++ code, I expected the output to be Abc, but, it was FFF, why is that? Isn't name pointing to a constant char?
#include <iostream>
int main()
{
const char* name = "Abc";
name = "FFF";
std::cout<<name<<std::endl;
return 0;
}
Yes, it's pointing to a const char as you say, but it is not a constant pointer. You are changing what you are pointing to, not the contents of what you are pointing to. In other words, the memory holding "Abc" still holds the characters "Abc" after you reassign the pointer.
For a constant pointer, you want const char* const name = "Abc";. In this case, it won't compile since you can't change what the pointer points to.
In general, with const and pointers in C++, you can read the type name from right-to-left to get a feel for what is going on. For example, in the const char* const case, you can read this as "a constant pointer to a character constant". A little weird, but it works.
const char* name = "Abc"; -> Non const pointer-> name, but data (Abc) is constant
name = "FFF" -> changing pointer(name) to point to FFF.
char *p = "Hello"; // non-const pointer,
// non-const data
const char *p = "Hello"; // non-const pointer,
// const data
char * const p = "Hello"; // const pointer,
// non-const data
const char * const p = "Hello"; // const pointer,
// const data
With const char* name = "Abc"; you are telling compiler you will not change the contents of "Abc" using name. However, you are free to change the pointer to point to a different memory location. See this FAQ for details.
It is a known issue with const and English speakers.
The syntax allows both:
const T
T const
and both have the same meaning.
However it becomes complicated once you throw a pointer in the mix:
const T* should be read (const T)*
T const* should be read (T const)*
T* const should be read (T*) const
For that reason I am an adept of always using const on the immediate right of the object. This is more consistent.
Note that the same issue can be found with typedef, let's define typedef T* pointer:
const pointer means T* const, not const T* (as a macro would imply)
pointer const means T* const, like the textual replacement
If you take the habit of putting the const after the name, and not before like an adjective in English, then you won't fall into those traps.
in deed the most correct syntax is
char const * pName;
because const keyword apply namely to the part on the left hand side.
if you want a const poitner to a const char you would write it:
char const * const pName;
and a const pointer to an int;
int * const pInt;
PS: but I still write the const at the begining of the line whenever I can, an anchored habbit ;-)
const char* name = "Abc";
Actually this means, name is a pointer to the const data. Means, it's the data which is const, not the pointer itself. So it's perfectly valid if you write:
name = "FFF"; //ok : changing the pointer
However, the following will not compile:
char * const name = "Abc"; //const pointer to the non-const data!
name = "FFF"; //error: trying to change the pointer itself!
See the compiler error:
prog.cpp:5: error: assignment of
read-only variable ‘name’
See yourself here : http://www.ideone.com/KyNXx
When you declare a variable as
const T* ptr = /*...*/
You are declaring a pointer saying that the object being pointed at, not the pointer, must not change. In other words, it's a "pointer to a T that's const."
If you want to make it impossible to reassign the pointer, you can write
T* const ptr = /*...*/
This is now an immutable pointer to a T, which can be modified.
You can combine these together like this:
const T* const ptr = /*...*/
To get an immutable pointer to an immutable T.
As a fun hint, you can usually determine what parts of a pointer/pointed pair can be modified by reading the type right-to-left. Try that out on the above and see what you get.
First, const is only checked at compilation time. If it compiles, all operations will be done normally at runtime.
In your example, const applies to the content pointed by name. So you are allowed to change the pointer, but not the content.
strcpy(name, "FFF");
would be refused, but not changing the pointer like you did.
The literal strings "Abc" and "FFF" are constant, but name is a variable (pointer to constant data). You have simply changed the variable to point to different constant data.
Moreover while in this case the data was necessarily constant, a pointer to constant data only means that the data cannot be modified by dereferencing that pointer, the data might also be modified directly or through a different pointer. E.g.
int i = 0 ;
const int* p = &i ;
i++ ; // valid
(*p)++ // error.

Declaration of pointers in C++

In C++ whats the difference between
char const *ptr=&ch;
and
const char *ptr=&ch;
They are the same, i.e. pointer to const char.
However char * const ptr is different, being a const pointer to (non-const) char.
And just to complete the set, const char * const ptr is a const pointer to const char.
No difference in C++.
It is important const is before * or after *.
Const applies to whatever is on its immediate left (other than if there is nothing there in which case it applies to whatever is its immediate right). So there is no difference.
char * const ptr would be a const pointer to variable value though.
Other answers have covered the technical solution - your two examples are the same.
Many people prefer to read from right to left when dealing with const in C++. In English, we like to think of a constant X, while C++ likes to parse an X const. Reading right to left yields a more English result.
A rather extreme example:
C const * bar(A * const, B const * const) const;
From right to left this reads as 'A constant function bar taking as parameters a constant pointer to an A and a constant pointer to a constant B, returning a pointer to a constant C'. Note that all three kinds of pointers are different.
char const *ptr=&ch; and const char *ptr=&ch; means char is const, where as the pointer is variable (or it can be changed).
But In case of char * const ptr, you cannot re-assign the pointer once you set it. so its a const pointer to a char string.

Double const declaration

I often see the following function declaration:
some_func(const unsigned char * const buffer)
{
}
Any idea why the const is repeated before the pointer name?
Thanks.
The first const says that the data pointed to is constant and may not be changed whereas the second const says that the pointer itself may not be changed:
char my_char = 'z';
const char* a = &my_char;
char* const b = &my_char;
const char* const c = &my_char;
a = &other_char; //fine
*a = 'c'; //error
b = &other_char; //error
*b = 'c'; //fine
c = &other_char; //error
*c = 'c'; //error
type declarations should(?) be read RTL. const modifies the thing on its left, but the rule is complicated by the fact that you can write both const T and T const (they mean the same thing).
T * const is a constant pointer to mutable T
T & const would be constant reference to mutable T, except references are constant by definition
T const * is a mutable pointer to constant T
T const & is a reference to constant T
T const * const is constant pointer to constant T
It's a constant pointer to a constant unsigned char. You can't change the pointer nor the thing it points to.
In a declaration like const * const T, the first const (before the *) means that what the pointer points at is const (i.e. it's a pointer to a const T). The const after the * means that the pointer itself is const (i.e. can't be modified to point at anything else).
You can read the declaration from the object being declared outward, so const unsigned char * const buffer is read as: "buffer is a const pointer to a const unsigned char" (this is why const should always being placed after what it modifies--with it before, you have to rearrange things to make the sentence--with it declared as unsigned char const * const buffer, translation to English is simple and straighforward (or perhaps "straightbackward", since you actually read from right to left in this case).
assuming const unsigned char * const
Everyone is correct that its a const pointer to a const unsigned char.
C++ types read mostly right to left unless there are any modifiers on the far left then these read left to right.
This makes it a const pointer to a const value, rather than a mutable pointer to a const value or a const pointer to a mutable value.
const * unsigned char const buffer means that you cannot modify the pointer buffer nor the memory that buffer points to.
A couple of articles to help you understand const correctness in C++:
Wikipedia
Possibility.com