Spidey
Spidey

Reputation: 2589

What would be an use case for a function returning a const pointer (int * const, for example)?

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?

Upvotes: 4

Views: 1101

Answers (4)

Adriano Repetti
Adriano Repetti

Reputation: 67090

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 = Π

// I have a constant pointer to a constant value, note that
const* int const pPI2 = Π

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

Upvotes: 4

Puppy
Puppy

Reputation: 146930

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.

Upvotes: 0

Luchian Grigore
Luchian Grigore

Reputation: 258618

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

Upvotes: 3

Richard J. Ross III
Richard J. Ross III

Reputation: 55573

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.

Upvotes: 1

Related Questions