views:

718

answers:

6

I am trying to use a return type of const MyClass * const. However, I get a warning:

Warning: #815-D: type qualifier on return type is meaningless.

Is this not a valid type? I want a pointer than cannot be changed, and I want the thing it points to to not be changed either.

A: 

the const qualifier doesn't mean anything because you're returning a pointer

DShook
+16  A: 

The pointer itself has value type, so it doesn't make sense to make it const. What the caller function does with the returned value can't be restricted by the called function. This is akin to trying to define something like:

const int getInt();

getInt(), in this case, just returns an int value (not a reference). It goes to a register, then the caller function receives it and does whatever it wants with it.

Juliano
So basically you can only define const return types with references?
Dynite
Yes (by reference, meaning both references and pointed objects). The pointer itself can't be const, it is just a value copied around.
Juliano
The pointer can't be const when returned from a function, but you can have a const pointer at a call site (see my answer below). This prevents someone from inadvertently reassigning to a pointer when you are actually using the pointer.
Nick Haddad
+4  A: 

Why do you care if the pointer is changed? Doing this is like saying:

const int f() {
   ...
}

The value returned by f() is a copy - changing it changes nothing, so there is nom point in making it const.

anon
I was thinking that I don't want people doing something like pointer++, because the size of each individual object is not the same.
Dynite
@Dynite, this is like giving people your address, eg 80, Main Street, and then wondering what will happen if they ring the bell on 81, Main Street.
Daniel Daranas
@Dynite - as daniel points out, they can do it anyway, so you gain nothing except some extra keyboard exercise
anon
@Dynite: they could do this without casting away constness or other ugliness just by doing `*(pointer+1)` so there really isn't much in the way of saftey that you're buying.
Michael Burr
+3  A: 

One simple way of making sure you're defining the return type you want is to always add modifiers on the right (as opposed to left) side of original type.

MyClass                 // MyClass object
MyClass const           // MyClass object which can't be modified
MyClass const &         // reference of an unmodifiable MyClass object 
MyClass const *         // pointer to an unmodifiable MyClass object
MyClass const * const   // unmodifiable pointer to an unmodifiable MyClass object
MyClass const * const & // reference of an unmodifiable pointer to an unmodifiable MyClass object

That should help make sure your return types are never meaningless again :)

Benoît
From the question: "pointer than cannot be changed, and ... the thing it points to to not be changed either." He declared the return type correctly based on his intentions.
Trent
Yes, he did. And he got only a compiler warning about meaningless of this stuff on return value.
dragonfly
+3  A: 

I agree with Juliano's answer, you want the constness of the pointer to be at the call site.

A better way to do what you are looking for is to have your function return a const reference to the object:

const MyClass& getMyClass()
{ 
  return myClass;
}

By definition references can't be modified, so you'd be better off.

Of course this won't work if your function is attempting to create a MyClass object. In that case you can just move the extra const to the call site.

// function definition
const MyClass* createMyClass()
{ 
  return new MyClass("I Love C++");
}

// use of a const pointer to a MyClass which is const
const MyClass* const myClassInstance = creatMyClass();
Nick Haddad
A: 

Why return a const value? Consider the following (and please excuse the unimaginative variable names):

struct A { int a; };

A operator+(const A& a1, const A& a2) 
{
    A a3 = { a1.a + a2.a };
    return a3;
}

Given that declaration of operator+, I can do the following:

A a = {2}, b = {3}, c = {4}, d = ((a+b) = c);

That's right, I just assigned to the temporary A that was returned by operator+. The resulting value of d.a is 4, not 5. Changing the return type of operator+ to const A prevents this assignment, causing the expression (a+b) = c to generate a compiler error.

If I try to assign to a pointer or integer returned from a function, my compiler (MSVC) generates a "left operand must be l-value" error, which seems consistent with the ARM compiler telling you that the constness of the pointer is meaningless--the pointer can't be assigned to anyway. But for classes/structs, apparently it's okay to assign to non-const return values.

bk1e