This question already has answers here:
Closed 12 years ago.
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).
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".
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:
Should useless type qualifiers on return types be used, for clarity?
Why is my return type meaningless?
where is rvalue stored in c?
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).
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.
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.
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.
Related
#include<iostream>
using namespace std;
int &fun()
{
static int x = 10;
return x;
}
int main()
{
fun() = 30;
cout << fun();
return 0;
}
Function fun() is returning value by reference but in main() method I am assigning some int to function. Ideally, a compiler should show an error like lvalue required but in above case the program works fine. Why is it so?
It's loose and sloppy language to say "a function returns something". It's OK as a shorthand if you know how to work with that, but in this case you get confused.
The more correct way to think about it is that you evaluate a function call expression. Doing that gives you a value. A value is either an rvalue or an lvalue (modulo details).
When T is an object type and you evaluate a function that has return type T, you get a value of type T which is an rvalue. On the other hand, if the function has return type T &, you get a value of type T which is an lvalue (and the value is the thing bound to the reference in the return statement).
Returning a reference is quite useful.
For example it's what std::map::operator[] does. And I hope you like the possibility of writing my_map[key] = new_value;.
If a regular (non-operator) function returns a reference then it's ok to assign to it and I don't see any reason for which this should be forbidden.
You can prevent assignment by returning a const X& or by returning X instead if you really want.
You can rewrite the code using pointers, which might be easier to understand:
#include<iostream>
using namespace std;
int *fun() //fun defined to return pointer to int
{
static int x = 10;
return &x; // returning address of static int
}
int main()
{
*fun() = 30; //execute fun(), take its return value and dereference it,
//yielding an lvalue, which you can assign to.
cout << *fun(); //you also need to dereference here
return 0;
}
References can be very confusing from a syntax point of view, as the dereferencing of the underlying "pointer" is implicitly done by the compiler for you. The pointer version looks more complicated, but is clearer or more explicit in its notation.
PS: Before someone objects to me regarding references as being a kind of pointer, the disassembly for both code versions is 100% identical.
PPS: Of course this method is a quite insidious breach of encapsulation. As others have pointed out, there are uses for this technique, but you should never do something like that without a very strong reason for it.
It works becuse the result of that function is an lvalue. References are lvalues. Basically, in the whole point of returning a non-const reference from a function is to be able to assign to it (or perform other modifications of referenced object).
In addition to other answers, consider the following code:
SomeClass& func() { ... }
func().memberFunctionOfSomeClass(value);
This is a perfectly natural thing to do, and I'd be very surprised if you expected the compiler to give you an error on this.
Now, when you write some_obj = value; what really happens behind the scenes is that you call some_obj.operator =(value);. And operator =() is just another member function of your class, no different than memberFunctionOfSomeClass().
All in all, it boils down to:
func() = value;
// equivalent to
func().operator =(value);
// equivalent to
func().memberFunctionOfSomeClass(value);
Of course this is oversimplified, and this notation doesn't apply to builtin types like int (but the same mechanisms are used).
Hopefully this will help you understand better what others have already explained in terms of lvalue.
I was buffled by similar code too - at fist. It was "why the hell I assign value to a function call, and why compiler is happy with it?" I questioned myself. But when you look at what happens "behind", it does make sense.
As cpp and others poined out, lvalues are "memory locations" that have address and we can assign values to them. You can find more on the topic of lvalues and rvalues on the internet.
When we look at the function:
int& fun()
{
static int x = 10;
return x;
}
I moved the & to the type, so it's more obvious we are returning a reference to int.
We see we have x, which is lvalue - it has address and we can assign to it. It's also static, which makes it special - if it wasn't static, the lifetime (scope) of the variable would end with stack unwinding upon leaving the function and then the reference could point to whatever black hole exists in the universe. However as x is static, it will exist even after we leave the function (and when we come back to the function again) and we can access it outside of the function.
We are returning reference to an int, and since we return x, it's reference to the x. We can then use the reference to alter the x outside of the function. So:
int main()
{
fun();
We just call the function. Variable x (in scope of fun function) is created, it has value of 10 assigned. It's address and value exist even after function is left - but we can't use it's value, since we don't have it's address.
fun() = 30;
We call the function and then change the value of x. The x value is changed via the reference returned by the function. NOTE: the function is called first and only after the function call was completed, then, the assignment happens.
int& reference_to_x = fun(); // note the &
Now we (finally) keep the reference to x returned by the function. Now we can change x without calling the function first. (reference_to_x will probably have the same address as the x have inside the fun function)
int copy_of_x = fun(); // no & this time
This time we create new int and we just copy the value of x (via the reference). This new int has its own address, it doesn't point to the x like reference_to_x is.
reference_to_x = 5;
We assigned x the value 5 through the reference, and we didn't even called the function. The copy_of_x is not changed.
copy_of_x = 15;
We changed the new int to value 15. The x is not changed, since copy_of_x have its own address.
}
As 6502 and others pointed out, we use similar approach with returning references a lot with containers and custom overrides.
std::map<std::string, std::string> map = {};
map["hello"] = "Ahoj";
// is equal to
map.operator[]("hello") = "Ahoj"; // returns reference to std::string
// could be done also this way
std::string& reference_to_string_in_map = map.operator[]("hello");
reference_to_string_in_map = "Ahoj";
The map function we use could have declaration like this:
std::string& map::operator[]( const std::string& key ); // returns reference
We don't have address to the string we "stored" in the map, so we call this overridden function of map, passing it key so map knows which string we would like to access, and it returns us reference to that string, which we can use to change the value. NOTE: again the function is called first and only after it was completed (map found the correct string and returned reference to it) the assignment happens. It's like with fun() = 10, only more beatiful...
Hope this helps anyone who still woudn't understand everything even after reading other answers...
L-value is a locator-value. It means it has address. A reference clearly has an address. The lvalue required you can get if you return from fun() by value:
#include<iostream>
using namespace std;
int fun()
{
static int x = 10;
return x;
}
int main()
{
fun() = 30;
cout << fun();
return 0;
}
In a book I'm reading about C++ (C++ for Dummies) there is a section that says the following:
int nVar = 10;
int* pVar = &nVar;
const int* pcVar = pVar; // this is legal
int* pVar2 = pcVar; // this is not
The book then goes on to explain:
The assignment pcVar = pVar; is okay -- this is adding the const
restriction. The final assignment in the snippet is not allowed since
it attempts to remove the const-ness of pcVar
My question is why is the last line not "legal". I don't understand how that impedes on the "const-ness" of pcVar. Thanks.
const int *pcVar = pVar;
int *pVar2 = pcVar;
If pcVar is const int *, that implies that the int it points to may be const. (It isn't in this case, but it may be.) So if you assign pVar2, which is a non-const int *, it still allows the int it points to to be modified.
So if pcVar actually pointed to a const int, and you assign an int * to its address, then that int * pointer (pVar2 in this case) will allow you, by dereferencing, to modify it, and that's illegal (it's a constraint violation, so it invokes undefined behavior).
All the compiler knows is that pcVar is a const int*. That is, it points to a const int. Just because you made it point at a non-const int doesn't matter. For all the compiler knows, the pointer value could have changed at some point to point at a truly const int. Therefore, the compiler won't let you convert from a const int* back to a int* because it would be lying about the constness of the object it was pointing at.
For a simpler example, consider:
const int x;
const int* pc = x;
int* p = pc; // Illegal
Here, x truly is a const int. If you could do that third line, you could then access the const int object through p (by doing *pc) and modify it. That would be bad - x is const for a reason.
However, in the example you gave, since you know that the original object was non-const, you could use const_cast to force the compiler into trusting you:
int* pVar2 = const_cast<int*>(pcVar);
Note that this is only valid if you know for certain that the object is non-const.
It's just saying you can't create a non-const pointer from one that was const (at least, not without a const_cast).
The idea behind const is to have objects that cannot be modified by accident. Getting rid of const through a simple assignment would be quite dangerous, and would allow things like this:
void function(int* m) {
*m = 20;
}
int main() {
const int x = 10;
//Oops! x isn't constant inside function any more, and is now 20!
function(&x);
}
Also, please check out The Definitive C++ Book and Guide List, it has lots of great references (C++ for dummies doesn't quite make the cut).
Mixing const and non-const is illegal. The reason being, if you tell the compiler that one location's value is const and then use another pointer to modify that value, you have violated the const contract you made with the first element.
pcVar stays the same but pVar2 points to a non-const, const can be added but not taken away. The compiler does not look at the original nVar being non-const, only the attempt to assign a const to a non const. Otherwise you could get around the const and change the value.
int * pVar = &nVar;
*pVar = 4 //is legal
const int* pcVar = pVar; // this is legal
*pcVar = 3 // this is not legal, we said the value was const thus it can not be changed
int* pVar2 = pcVar; // this is not legal because...
*pVar2 = 3 -> *pcVar = 3
The second line
int pVar = &nVar;
is error.
g++ compiler says.
error: invalid conversion from ‘int*’ to ‘int’
I need to clear a basic concept. This code works fine. Can somebody explain me that if the function calDouble already returning the address (reference) of int why I need to use & operator further in main int *j = &calDouble(i); to get the address (reference) of int? Thanks.
int& calDouble(int x)
{
x = x*2;
return x;
}
int main(int argc, char *argv[])
{
int i = 99;
int *j = &calDouble(i);
system("PAUSE");
return EXIT_SUCCESS;
}
int& calDouble(int x) doesn't return an address, but a reference to an int.
You need to take the address of the reference to be able to assign it to a pointer.
Note however that your code invokes undefined behavior. Because you pass the parameter by value, a copy of it is created inside the function. So you return a local variable by reference, which is not legal.
I think your confusion comes from &. This can be used in two ways:
applied to a variable &x, it takes its address
when in a declaration int& x, it defines a reference
A reference is just an alias, a different name for a variable.
int x = 0;
int& y = x;
Now, x and y refer to the same variable.
int* z = &x;
takes the address of x.
int& is a reference type. It is not the address.
To see what &calDouble(i) does, consider if we had broken it into two statements:
int& x = calDouble(i);
... = &x;
The calDouble() function returns a reference type, and the prepended & then takes the address-of whatever was returned. So the type is now int*, which is why that line compiles.
However, your program exhibits undefined behavior! The x in calDouble() goes away once the function ends. The value that was originally there may still be in memory, which is why your program "works". But this is not reliable in production code, and one day your perfectly working test program may blow-up the moment it's deployed.
It's generally a bad idea to return a reference to a local variable for this vary reason. (You'll see class methods return references to member data, which is fine as long as the object is still in scope since those variables will still exist.) Just return a regular int and get on with life. An optimizing compiler can do some return value optimization if you're really worried about performance when returning large objects.
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.
I have just started C++ and have come across references and have not understood completely.
References , as i read is an alternative name for an object.Why use that instead of directly accessing the object as any operation on references is directly reflected on the object ...?
Why and when are they used ?
Is ist like a constant pointer that is referenced each time it is used ... ?
And , it says
double& dr = 1; ---- says it is an error (some lavalue needed)
const double& cdr = 1; ---- says it is ok.
i dont understand it properly..So please explain why it is so ...
Thank You...:)
Why use that instead of directly
accessing the object as any operation
on references is directly reflected on
the object ...?
C++ passes parameters by value, meaning if you have a function such as:
void foo(MyObject o) { ... }
By default C++ will make a copy of a MyObject, not directly use the object being passed in. So, one use of references is to ensure you are working on the same object:
void foo(MyObject &o) { ...}
Or, if you aren't modifying o:
void foo(const MyObject &o) { ... }
References are another way of what was originally in C code like this
void fubarSquare(int *x){
int y = *x;
*x = y * y;
}
// typical invocation
int z = 2;
fubarSquare(&z);
// now z is 4
with references in C++ it would be like this
void fubarSquareCpp(int& x){
x = x * x;
}
// typical invocation
int z = 2;
fubarSquareCpp(z);
// now z is 4
It's a neater syntactical way of using a call-by-reference parameter instead of using the C's notation asterisk/star to indicate a pointer and as a call-by-reference parameter...and modifying the parameter directly outside of the function...
Have a look at Bjarne Stoustrap's page here which covers how C++ is and also here on the technical faq here
A reference is basically a pointer that looks like an object. It is very very hard to get a NULL reference though you can go through hoops and create one.
With regards to your example, 1 is an rvalue or a result. It is just a temporary variable and can not be modified. Thus you can't take a non const reference to it. However you can take a const reference to it. This means you can't change the value of the reference.
Here is an example of creating a NULL reference. Don't do it!
int * x = (int *)NULL;
int & y = *x;
I agree with you. using references as just an alias name is not very useful.
It is more useful if you consider it as an immutable pointer. But not that useful in fact.
Practically, it is used to define clean interfaces. For example when you define:
int foo(const int& param);
You say that param is a read-only parameter in foo.
Do not forget that you MUST assign a value to a reference.
See the C++ faqlite on references for more
my2c
References improve the syntax, so no pointer dereference needed.
Assuming Base is a class that may be derived from:
void someFunction(Base b)
{
b.function();
// b is a copy of what was passed - probably performance issues
// possible unintended object slicing - you only get the Base part of it
// no virtual function call
// no changes to b visible outside the function
}
void someFunction(Base* b)
{
b->function();
// a shortcut for (*b).function();
// b is the same object that was passed to the function
// possible virtual call
// changes visible outside the function
}
void someFunction(Base& b)
{
b.function();
// b is the same object that was passed to the function
// possible virtual call
// changes visible outside the function
}
References are like constant pointers (NOT pointers to constants - i.e. you can change the object, but you can't change to what you're pointing). const reference is a reference through which you can do things that can be done on const object.
References are also good, because you can't have a null reference
Give the wikipedia article a good read through. To sum it up, references are more friendly version of pointers which are commonly used to pass objects as references into functions without worrying about a null pointer.
To explain the example:
Think of the number 1 represented as a variable. When compiled, this number is put into the global section of the memory which can be referenced by the program, but not modified.
So it is of type: const int
double &dr = 1 is trying to assign dr (a reference to a double) to the const int 1. Since 1 is a constant, the compiler will not allow you to make a non-constant reference to it.
In the second line:
const double &dr = 1 is trying to assign dr (a constant reference to a double) the const int 1. This works because the reference is also const and therefore can point to a const int.
EDIT
The const int is converted to a const double before assigned.
References are language entitities that represent another object they refer to. Nonconst references are lvalues, and must be initialized with an lvalue. They can be useful like this:
int& x=condition ? array[1] : array[2];
int& y=condition ? array[0] : array[3];
x+=y;
y=0;
When used as a function parameter, they tell the caller he has to pass an lvalue that might be written to by the function:
void set1(int& x) { x=1; }
int foo;
set1(foo); // ok, foo is 1
set1(foo+1); // not OK, not lvalue
Const references, on the other hand, can be bound to rvalues. In function parameters, they are usually used to avoid excessive copies:
void niceness(std::string s); // the string would be copied by its copy-ctor
void niceness(const std::string& s); // the caller's string would be used
Note that this may or may not yield faster code.
When const-references are used in normal code, they can bind rvalues, too, and as a special rule, they extend the lifetime of the object they are bound to. This is what you saw in your code:
const double& d=1; // OK, bind a rvalue to a const-ref
double& d=1; // Bad, need lvalue
All references are polymorphic, like pointers:
class A { virtual void f(); }
class B : public A { void f(); }
B b;
A& ar=b;
ar.f(); // calls B::f()
and all references are aliases like pointers:
int f(int& a, const int& b)
{
a=1;
return b;
}
int x;
f(x, 42); // ==42, foo=1
x=42;
f(x, x); // ==1 (not 42), foo=1
double& dr = 1; // 1.0 would be more clear
Is invalid because 1 is viewed to be of type const double so if you want a reference to that variable you need to have a reference to a const double so
const double& dr = 1.0;
Is correct.
Utility of references is most visible in the context of passing parameters to functions.
I.e,
int a;
func definition: void foo (int& param) {param = 1;}
func call: foo(a);
The way as 'param' aliases 'a' is clean and its intention is easily understood by a reader of this code as well as compiler that may optimize away when inlining any additional memory allocation needed for the reference.
Passing a reference to a function and then having the function use the reference is almost like passing a pointer to the function and then having the function dereference the pointer. In many cases, the machine-code implementation will be identical. There are some differences, though, especially in the case of functions that get expanded inline. If a variable is passed by reference to an inline function, the compiler will often be able to substitute the variable itself--even if stored in a machine register--when expanding the function. By contrast, if one takes the address of a variable and passes that as a pointer to a function which then dereferences it, the compiler is less likely to figure out that optimization unless it determines not only that--at least for one particular expansion of the function--the pointer will always point to that variable, but also that the pointer will not be used anywhere else (if the pointer was used elsewhere, the variable could not be kept in a register).