views:

135

answers:

6

Possible Duplicate:
Why is my return type meaningless?

Hi, I'm confused about a particular const conversion. I have something like

// Returns a pointer that cannot be modified,   
// although the value it points to can be modified.  
double* const foo()  
{  
    static double bar = 3.14;  
    return &bar;  
}

int main()  
{  
    double* const x = foo(); // fine  
    const double* y = foo(); // eh?!  
    return 0;  
}

When I compile this on MSVS 2008 (Express) there is no error, but it seems to me like there should be. The meaning behind x and y are quite different, so it does not seem like there should be this implicit conversion. So is this an issue with the compiler (unlikely), or my understanding of the const-ness involved here (quite likely).

+3  A: 

As has been asked many other times in many other questions, returning a const value from a function is meaningless. A function returns an rvalue, which by definition cannot be modified. The fact that you can assign it to another variable is no real surprise. Check out these questions & answers for more information:

Carl Norum
"Returning a const value from a function is meaningless" - this is only true for built-in types. When it comes to class types, returning const or non-const (even by value) does make a difference.
AndreyT
+1  A: 

The return value cannot be modified. That is, the pointer cannot be modified. However, because at the call site, the return value is an rvalue (without a defined = operator), it cannot be modified anyway.

If the return value was an lvalue (e.g. a reference), this would be possible:

double* &foo()
{
    static double bar = 3.14;
    double *barP = &bar;
    return barP;
}

double myDouble;
foo() = &myDouble;

But this would not be possible:

double* const &foo()
{
    static double bar = 3.14;
    double *barP = &bar;
    return barP;
}

double myDouble;
foo() = &myDouble; // error!

Adding const to the return value (as to quality the pointer as const, not the pointed to data as const) in your case does nothing. If anything, your compiler should warn you about this, because really there's no different if you just remove the const qualifier (barring possible ABI changes, though I'm not sure if the standard allows for ABI changes in this case).

strager
+7  A: 

What you did is equivalent to the following:

const int a = 5;
int b = a;

This is (as you probably know) perfectly valid as it creates a copy of the variable. If you do b = 10, a remains 5, so the constness isn't "broken".

Andreas Bonini
Good example! +1
strager
A: 

You can always assign an X const, a constant X, to a variable X -- the variable may later be modified, perhaps, but what an X const guarantees is that itself won't be modified, not of course that any copy of it will never be. In your case X is a pointer type, but that does not change this rule.

You can always assign a const X* variable from an X* value: the pointed-to data won't be modified through the pointer variable you have thus assigned (that's what its const means), but of course they may be modified through other pathways.

So in this case you're doing both perfectly legitimate assignments at the same time: there's no reason why the combination of the two legal things should be illegal, in this case, since no expressed constraint is violated anyway.

Alex Martelli
A: 

Use the right-left rule to understand the return type of 'foo'. 'foo' basically returns a (also cross validate through cdecl.org)

const pointer to double

A "const pointer to double" is not the same as "pointer to const double".

In the first case, pointer is const, pointed to value can change.

In the second case, the point can change, the pointed to value cannot change.

Chubsdad
A: 

Hey jdowner, although these answers here most likely answer your questions, I also highly recommend you read this article regarding const correctness. It goes over all of the possible scenarios and what they mean in plain english.

Jorge Israel Peña