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.
Related
Today I noticed something strange about the type of 'this'. If you have something like this:
class C {
void funcA() {
funcB(this);
}
void funcB(C obj) {
//do something
}
};
You will of course get an error, because funcB() expects an object, while 'this' is a pointer. I accidentally did forget the asterisk, but was surprised by the error message, as it said:
no matching function for call to 'C::funcB(C* const)'
Where does the const come from, when funcA() is not constant?
That's saying that the this pointer itself as const -- i.e., you can't modify the pointer to point to different memory.
Back in the very early history of C++, before you could overload new and delete, or placement new was invented, this was a non-const pointer (at least inside the ctor). A class that wanted to handle its own memory management did so by allocating space for an instance in the constructor, and writing the address of that memory into this before exiting the constructor.
In a const member function the type you'd be dealing would be Class const *const this, meaning that what this points at is const (as well as the pointer itself being const).
C* const does not mean that the object of type C is constant. That would be C const* or const C*.
C* const means that the pointer itself is constant.
Which makes sense, since you cannot do
this = &something_else;
There is a difference between C const* and C * const. You need to understand the difference:
C const* means it is the object (pointed to by the pointer) which is constant.
C * const means it is the pointer itself which is constant.
So this by definition is a pointer of C * const type, so it cannot be modified, though the object pointed to by it can still be modified.
Note that it's not C const *, but C* const. I.e. (reading from right to left) constant pointer to C.
The pointer itself is constant, not the data pointed to.
The title is self explanatory, but I'll give an example anyways.
int sum(int a, int b){
return a + b;
}
We could rewrite it as
int sum(const int a, const int b){
return a + b;
}
But what about returning a const int? Is it useful in any way?
const int sum(const int a, const int b){
return a + b;
}
The caller will have to copy the const return to a const lvalue. Is this too restrictive? Do you know any use cases where this could be a good design choice?
Ok, I wasn't clear at the question body. Think about a sum function that works similar to assembly add:
int *sum(int *a, int b){
*a += b;
return a;
}
Add the const's to the params:
int *sum(int * const a, const int b){
*a += b;
return a;
}
What about making the return const too? Is there a reason for this?
There are a lot of situations where you may return a const pointer or a const object. I can't imagine any real situation where you want to return a primitive type as const.
I'm not sure what's your question, in the title your' talking about int* const but in the code example you have a const int.
Some examples (in C++) follows for different combinations of const and T*.
Pointer to const (primitive type)
const int* someFuncion();
You have a pointer to a constant, it means you can change the pointer but you can't change the pointed object/value. Please note that someFunction() must not return a pointer (const or not) to a stack allocated variable. I assume the pointer is valid. For example:
const int* value = someFunction();
// Next line is valid, value will hold a new pointer
value = anotherFunction();
// Next line is not valid, pointed value cannot be changed
*value = 10;
Pointer to const (object)
const T* someFunction();
You have a pointer to a constant. It means you can change the pointer to point to another object but you can't change the pointed object state. This doesn't mean you can't use that object, only that the object is const then you can use only its methods marked as const, read its fields and write its mutable fields. A constant method is defined as:
void method() const;
It can have any return type and any parameter the point is that it's marked with the const modifier. It means that it won't change the object state (again with the exclusion of mutable objects).
Now an example, with T declared as:
class T
{
public:
void dump() const
{
// Dump the value to console, for example
}
void increaseValue()
{
++m_value;
}
private:
int m_value;
};
Imagine to write following code:
const T* value = someMethod();
// Next line is valid, value will hold a new pointer
value = anotherMethod();
// Next line is not valid, we cannot change the object state
value->increaseValue();
// Next line is valid, we do not change the object state
value->dump();
Constant pointer (primitive type)
int* const someFunction();
You have a constant pointer, it means you can change the pointed value but you cannot assign another memory location to the pointer itself. For example:
int* const value = someFunction();
// Next line is not valid, value cannot be changed
value = anotherFunction();
// Next line is valid, you can change the variable pointed by value
*value = 10;
Constant pointer (object)
T* const someFunction();
You have a constant pointer, it means you can change the pointed object state but you cannot assign another memory location to the pointer itself. For example:
T* const value = someFunction();
// Next line is not valid, value cannot be changed
value = anotherFunction();
// Next lines are both valid, we can do whatever we want with the object
value->increaseValue();
value->dump();
Constant pointer to a constant
const int* const someFunction();
This is the mix of previous declarations. All (restrictive) rules described above are valid. It means you can't change the pointer and you can't change the pointed value.
Notes
The const modifier is not restricted to be used to pointers and functions return value. For example:
// PI value cannot be changed
const int PI = 3.14f;
// I have a pointer to a constant value
const* int pPI = &PI;
// I have a constant pointer to a constant value, note that
const* int const pPI2 = &PI;
Remember that the const modifier can always be removed using a C-style cast or a const_cast.
Conclusions
So, going back to your question, is it useful a function with a const int return value?
If it's a pointer my answer is yes, even if it can be removed with a cast: the purpose of const is to communicate intentions (saving you from stupid errors hard to find) so more your function communicates and better it'll be used. Updating this from your last example my answer is yes, use const wherever appliable. Who will call your code will thank you (and you'll do it with yourself).
If it's just a const int (or another primitive type) it may be very rare you have to write something like that. Very often they're just intermediate results of a long calculation then it's useless to declare them as const (primitive types won't change but will be combined to create a new value). Note, however, that if it make some sense to declare them as const then you should do it. I guess it's more common to see a constant primitive type declared as local variable (again to be sure it won't be changed by mistake). For example:
// This local variable cannot be modified
const int rate = (calculateX() + calculateY()) / calculateRateFactor();
Or in functions, why not? If you always use this rule (const if shouldn't be changed) you'll see on-the-fly when a parameter isn't const then you'll understand you'll modify it somewhere (maybe with a small, hidden, pretty ++ at the most right character of your screen).
// With this prototype I'm sure I won't change a or b by mistake inside
// the function body.
int someFunction(const int a, const int b);
For objects I think it's even more common to use the const modifier (because a const T return type makes sense very often), for example:
// This object cannot be changed, just moved all around
const order* getNextOrderToStore();
Topic isn't ended, of course, because of aliases, mutables, operators overloading and the differences between C and C++...
I can only see this as a good thing as a statement of intent.
Something more in the sense of - if you get this value, you shouldn't need to change it, more than don't change this value.
This actually accomplishes nothing other than intent, as you're able to change the value anyway: http://ideone.com/Mf8Ge
No, I see few situations where this would be useful, as it really accomplishes nothing, and it restricts what the caller can do with the return value.
The caller will have to copy the const return to a const lvalue.
No, it won't at all. In fact, it might not ever copy it. Or it might copy it to a mutable lvalue.
There is no sense in const rvalues, there never has been, and there never will be.
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.
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.
I apologize if this has been asked, but how do I create a member function in c++ that returns a pointer in the following scenerios:
1. The returned pointer is constant, but the junk inside can be modified.
2. The junk inside is constant but the returned pointer can be modified.
3. Neither the junk, nor the pointer can be modified.
Is it like so:
int *const func() const
const int* func() const
const int * const func() const
All of the tutorials I've read don't cover this distinction.
Side note:
If my method is declared const then the tutorials say that I'm stating that I won't modify the parameters.. But this is not clear enough for me in the case when a parameter is a pointer. Do my parameters need to be like:
a. void func(const int* const x) const;
b. void func(const int* x) const;
c. void func(const int* const x) const;
I don't know what book you have read, but if you mark a method const it means that this will be of type const MyClass* instead of MyClass*, which in its turn means that you cannot change nonstatic data members that are not declared mutable, nor can you call any non-const methods on this.
Now for the return value.
1 . int * const func () const
The function is constant, and the returned pointer is constant but the 'junk inside' can be modified. However, I see no point in returning a const pointer because the ultimate function call will be an rvalue, and rvalues of non-class type cannot be const, meaning that const will be ignored anyway
2 . const int* func () const
This is a useful thing. The "junk inside" cannot be modified
3 . const int * const func() const
semantically almost the same as 2, due to reasons in 1.
HTH
Some uses of const don't really make much sense.
Suppose you have the following function:
void myFunction (const int value);
The const tells the compiler that value must not change inside the function. This information does not have any value for the caller. It's up to the function itself to decide what to do with the value. For the caller, the following two function definitions behave exactly the same for him:
void myFunction (const int value);
void myFunction (int value);
Because value is passed by value, which means that the function gets a local copy anyway.
On the other hand, if the argument is a reference or a pointer, things become very different.
void myFunction (const MyClass &value);
This tells the caller that value is passed by reference (so behind the screens it's actually a pointer), but the caller promises not to change value.
The same is true for pointers:
void myFunction (const MyClass *value);
We pass a pointer to MyClass (because of performance reasons), but the function promises not to change the value.
If we would write the following:
void myFunction (MyClass * const value);
Then we are back int he first situation. myFunction gets a pointer, which is passed by value, and which is const. Since MyFunction gets a copy of the pointer value, it doesn't matter for the caller whether it is const or not. The most important thing is that myFunction can change the contents of value, because the pointer variable itself is const, but the contents in it isn't.
The same is true for return values:
const double squareRoot(double d);
This doesn't make any sense. squareRoot returns a const double but since this is passed 'by value', and thus needs to be copied to my own local variable, I can do whatever I want with it.
On the other hand:
const Customer *getCustomer(char *name);
Tells me that getCustomer returns me a pointer to a customer, and I am not allowed to change the contents of the customer.
Actually, it would be better to make the char-pointer-contents const as well, since I don't expect the function to change the given string:
const Customer *getCustomer(const char *name);
int *const func() const
You cannot observe the const here except for a few cases
Taking the address of func.
In C++0x, directly calling func with the function-call syntax as a decltype operand, will yield int * const.
This is because you return a pure pointer value, that is to say a pointer value not actually stored in a pointer variable. Such values are not const qualified because they cannot be changed anyway. You cannot say obj.func() = NULL; even if you take away the const. In both cases, the expression obj.func() has
the type int* and is non-modifiable (someone will soon quote the Standard and come up with the term "rvalue").
So in contexts you use the return value you won't be able to figure a difference. Just in cases you refer to the declaration or whole function itself you will notice the difference.
const int* func() const
This is what you usually would do if the body would be something like return &this->intmember;. It does not allow changing the int member by doing *obj.func() = 42;.
const int * const func() const
This is just the combination of the first two :)
Returning a pointer to const makes a lot of sense, but returning a const pointer (you cannot modify) usually adds no value (although some say it can prevent user errors or add compiler optimisation).
That is because the return value belongs to the caller of the function, i.e. it is their own copy so it doesn't really matter if they modify it (to point to something else). The content however does not "belong" to the caller and the implementor of the function may make a contract that it is read-only information.
Const member functions promise not to change the state of the class, although this is not necessarily enforced in reality by the compiler. I am not referring here to const_cast or mutable members so much as the fact that if your class itself contains pointers or references, a const member function turns your pointers into constant pointers but does not make them pointers to const, similarly your references are not turned into references-to-const. If these are components of your class (and such components are often represented by pointers) your functions can change their state.
Mutable members are there for the benefit of allowing your class to change them whilst not changing internal state. These can typically be applied to:
Mutexes that you wish to lock even for reading.
Data that is lazy-loaded, i.e. filled in the first time they are accessed.
Reference-counted objects: You want to increase the reference count if it has another viewer, thus you modify its state just to read it.
const_cast is generally considered a "hack" and is often done when someone else has not written their code properly const-correct. It can have value though in the following situations:
Multiple overloads where one is const and one non-const and the const returns a const-reference and the non-const returns a non-const reference, but otherwise they are the same. Duplicating the code (if it is not a simple data member get) is not a great idea, so implement one in terms of the other and use const_cast to get around the compiler.
Where you want in particular to call the const overload but have a non-const reference. Cast it to const first.
The const method prevents you from modifying the members. In case of pointers, this means you can't reassign the pointer. You can modify the object pointed at by the pointer to your heart's desire.
As the pointer is returned by value (a copy), the caller can't use it to modify the pointer member of the class. Hence adding const to the return value adds nothing.
Things are different if you were to return a reference to the pointer. Now, if the pointer weren't const, this would mean that a function that doesn't have rights to modify a value is granting this right to the caller.
Example:
class X
{
int* p;
public:
int* get_copy_of_pointer() const //the returned value is a copy of this->p
{
*p = 42; //this being const doesn't mean that you can't modify the pointee
//p = 0; //it means you can't modify the pointer's value
return p;
}
int* const& get_reference_to_pointer() const //can't return a reference to non-const pointer
{
return p;
}
};