I have a struct
struct Stuff {
float something (int& prereq) {
float s = prereq+2;
return s;
}
double something_else(int& prereq_ref, float& thing_ref, float& s_ref ){
s2 = s + thing + h;
return s2;
}
};
Then I run a call in my main loop
float thing = 4;
int prereq = 2;
int main() {
Stuff item;
double n = item.something_else(prereq, thing, item.something(prereq));
return 0;
}
The call in main doesn't run, however the following line does
float s = item.something(prereq);
double n = item.something_else(prereq, thing, s);
Am I missing something obvious? I'd rather not waste memory on what seems to be an unnecessary float.
float& is an lvalue reference type. It can only take values that can be assigned to, such as variables.
float s = item.something(prereq);
double n = item.something_else(prereq, thing, s);
Here, s is a variable. It has a place in memory and the expression s = ... would be meaningful. On the other hand,
double n = item.something_else(prereq, thing, item.something(prereq));
Here, the value is item.something(prereq), which is not an lvalue. We can't write item.something(prereq) = ...; it doesn't make sense to assign to the return value of that function.
If you're not planning to modify the function arguments, take them by constant reference or by value.
double something_else(const int& prereq_ref, const float& thing_ref, const float& s_ref)
or
double something_else(int prereq_ref, float thing_ref, float s_ref)
for large data like structures or classes, you might consider using const&, but for integers and floats, it's unnecessary overhead and by-value parameters will do fine.
int foo(int & arg);
This function signature says:
"I will take a reference to the variable you pass in, and I may change it while computing my return value."
If that statement is not true, then your function signature is wrong, or at least misleading to anyone looking at it. It's also worth noting, that if you compute a temporary, it's not in a variable and so it's ineligible to pass into this function. That is the problem you're running into.
Note, this style of function signature is what's known as an "out" parameter (non-const lvalue reference) because it can be thought of as returning an OUTput through a parameter. This design approach is discouraged if other approaches are available, and so it is actually somewhat rare. Any time you find a function with a non-const reference parameter, be sure it's what you mean.
Compare it to this:
int foo(int arg);
This function says:
"I get my own copy and don't care what it came from, variable, reference, temporary, whatever, and I will leave your origianl value alone when computing my return value."
This clearly is what you want to say, so drop the & in your parameter list.
Related
I am calling a function with the signature
void setValue(int& data)
I would like to pass a literal number to it:
setValue(1);
But I get:
error: invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int'
Is there a way I can make this work without changing the function (it's in a library) and without assigning each literal value to a variable?
Assuming setValue does not actually modify its argument and just has a wrong signature which you cannot change, here is an approach which is not thread-safe among other things:
#include <iostream>
void setValue(int &i)
{
std::cout << "i = " << i << std::endl;
}
int& evil(int i)
{
static int j;
j = i;
return j;
}
int main()
{
setValue(evil(1));
setValue(evil(2));
}
When you declare the argument as being an int&, you are saying that the function called can change the value and the caller will see the change.
So it is no longer valid to pass a literal value then because how could the function possibly change the given value of a literal?
If you don't want the setValue to be able to change the given value, make the argument either be an int or const int&. And if you do want the setValue function to be able to change the value, then the caller must declare a non-const variable to hold the int and pass in that.
Can I change something at the call site to make it work
The problem with your code is that you declared your function to expect a reference, which means the compiler has to prepare the code to allow the function to change whatever you pass into it at the call site. So yes, sure, you can declare a variable, set it to 1 and call your function with it.
Contrast this with a constant reference in the declaration, where the compiler knows you won't change it inside the function, and then you can pass a literal in without issues. In fact, any logical, thought out design will make setters accept constant parameters because it won't change them, it will just store a possibly processed value in its state.
The answer to „what do I do if a library has a bad interface and I can't change it“ is usually „write a wrapper“. Assuming this is a method of some class BadLibraryClass, you could do something like:
class Wrapper {
public:
BadLibraryClass inner;
setValue(int i) {
inner.setValue(i); // i is an lvalue
}
};
This is just a crude example. Perhaps inner is better off being a pointer, a reference or even a smart pointer. Perhaps you want a conversion operator to BadLibraryClass. Perhaps you can use inheritance to expose other methods of BadLibraryClass.
Two options:
Use the result of assignment:
static int _data;
void myCall() {
setValue((_data = 3));
}
Write a wrapper:
struct setValueW {
int _data;
// constructor
setValueW(int _data) : _data(_data) {
setValue(_data);
}
// if you want to call it again
void operator()() {
setValue(_data);
}
};
void myCall2() {
setValueW(3);
}
AFAIK, references keeps the addresses of the variable. 1 is not variable. It is temporary.
Take a look this article(this is a quote from this site)
c++11 introduced a new kind of reference variable -- an r-value reference
To declare one, use && after a type
int & // type designation for an L-value reference
int && // type designation for an R-value reference
L-value references can only refer to L-values
R-value references can reference to R-values (temporaries)
int x, y, z; // regular variables
int & r = x; // L-value reference to the variable x
int & r2 = x + y; // This would be ILLEGAL, since x + y is an R-value
int && r3 = x + y; // LEGAL. R-value reference, referring to R-value
So you can use (But this is not useful. It may be more useful if you write this in plain without rvalue or lvalue.):
void setValue(int&& data)
setValue(1);
Or you can use that:
void setValue(int& data)
int a = 11;
setValue(a);
Don't forget for second example. If you change the value of data parameter. You will have change the a variable value.
No, you can't.
An lvalue reference like that binds to a variable (roughly speaking).
Your literal is not such a thing. It never had a name, and may not even have a home in memory.
Your two options are the two things you ruled out, I'm afraid.
For what it's worth, this is not your fault: that is a rather poor setter. It should take const int& (which will automatically create a nice temporary variable for you out of the literal!), or even just const int.
Why these definitions are all ok:
int func(int p=255) {
return p;
}
int func1(const int &p=255) {
return p;
}
but this definition:
int func2(int &p=255) {
return p;
}
leads to compile error ?
What is the logic behind it ?
Taking arguments by reference means, you dont work with your local copy of the variable, but with a variable already defined in the scope of the calling function.
While your first example makes sense (you have a local variable p that you can fill with a default value) the second example is a bit more tricky: Usually when using references you expect the variable to have an address, since you want to modify it. For const-refernces, the compiler will still allow you to pass a literal, even if something like "reference to a literal" makes no sense at all.
In the third case the compiler expects you to modify p. But what part of the memory should this modification affect? "255" has no address - therefore it cant be used as a reference.
If you want to have a more detailed explanation, you should probably look for keywords like "rvalue" and "lvalue".
The attempted function definition
auto func2( int& p = 255 )
-> int
{ return p; }
… fails because you can't bind an rvalue to a reference to non-const. Basically that rule is because a simple value like 255 isn't modifiable. While the reference can be used to modify.
One simple solution is to express the default as a separate overload:
auto func2( int& p )
-> int
{ return p; }
auto func2()
-> int
{
int scratchpad = 255;
return func2( scratchpad );
}
A non-const reference must be bound to lvalue (i.e. its address could be got). 255 (i.e. an int literal) is not a lvalue, so int &p=255 fails.
A const reference could be bound to rvalue, and for this case, a temporary int will be created and initialized from 255. The temporary int's lifetime will be the same as the const reference.
int func(int p=255) {
return p;
}
p here is copied by value, and it is defined to exist in the scope of func.
int func2(int &p) {
return p;
}
// e.g. use:
int value = 10;
func2(value); // func2 *could* modify value because it is passed by non-const reference
In this case the compiler here expects p to have a name somewhere in memory (i.e. lvalue), so it can possibly write to it within func2. Passing by non-const reference allows you to modify the variable used in the function call. Since p must belong to someone else somewhere since it can be modified, you can't assign a default value to it.
But what about the const-reference case? Here, the compiler is smart enough to know that p can never be written to since it is const, so it doesn't need to have a name in memory to write to. In cases of a literal being passed (e.g. 255), it (behind the scenes) essentially creates a temporary and passes that temporary variable to the function.
int func1(const int &p=255) {
return p;
}
func1(10);
// Behind the scenes, the compiler creates something along these lines
// since it can never be modified.
const int some_temporary = 10;
func1(some_temporary);
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.
With C++, I struggle to understand one compilation error.
I have this function, with this given signature:
void MethodNMMS::tryNMSA(double factor, double temperature,double& funcWorst,int& iWorst, double& funcTry, double* funcEvals)
{
//...
}
My question concerns argument double& functry (for instance). I call this function tryNMSA() in another function, and I would like functry to be modified during execution of this function. That is why I pass by reference.
Here is the function call:
// other initializations for funcEvals...
double funcTry = 0;
tryNMSA(-1.0,temperature,funcWorst,iWorst,&funcTry,funcEvals);
I put this ampershead because I do want to pass the thing by reference. And that is not permitted. What is wrong, why?
Thanks and regards.
You should not put an ampersand there, as doing so gives a pointer, not a reference to funcTry. Getting a reference to a variable doesn't require any special symbols or operators - just use the name of the variable.
Simply remove the & when you call the function - adding the & means you're trying to pass a pointer.
If you don't put the &, you'll pass a reference. No special syntax necessary.
By passing &funcTry, you are passing the address of funcTry, which would match a function expecting a pointer to double. Your call should simply be
ryNMSA(-1.0,temperature,funcWorst,iWorst,funcTry,funcEvals);
Outside of declarations, a single ampersand means address-of, so &foo means address-of foo.
You should omit the ampersand on the call like this:
tryNMSA(-1.0,temperature,funcWorst,iWorst,funcTry,funcEvals);
The ampersand in the method declaration marks it as a reference argument. When you do ampersand in the method call, you are passing the address of the funcTry variable which is immutable and can't be passed by reference, so compiler gives you an error.
Delete the & in front of the parameter.
Info here:
http://pages.cs.wisc.edu/~hasti/cs368/CppTutorial/NOTES/PARAMS.html
Reference Parameters
When a parameter is passed by reference, conceptually, the actual parameter itself is passed (and just given a new name -- the name of the corresponding formal parameter). Therefore, any changes made to the formal parameter do affect the actual parameter. For example:
void f(int &n) {
n++;
}
int main() {
int x = 2;
f(x);
cout << x;
}
In this example, f's parameter is passed by reference. Therefore, the assignment to n in f is actually changing variable x, so the output of this program is 3.
I won't repeat the other answers. I just wanted to say that this is a recurring issue with learners of C++. The problem is that the & sign has three completely different meanings, and this is not immediately obvious to a beginner:
If x is an l-value, then &x is its address.
If <type> x declares a variable of type <type>, then <type> &x declares a variable of type reference to <type>.
a & b is the bitwise-and operator.
This is similar to the * sign:
If x is a pointer, then *x is its contents.
If <type> x declares a variable of type <type>, then <type> *x declares a variable of type pointer to <type>.
a * b is the multiplication operator.
For some reason, the * operator seems to cause fewer problems than the & operator. Perhaps this is just historical accident: references are newer than pointers.
You can modify a parameter in 2 ways.
Method 1: (reference):
void MethodNMMS::tryNMSA(double& funcTry)
{
funcTry = funcTry + 1.0;
//...
}
// other initializations for funcEvals...
double funcTry = 0;
tryNMSA(funcTry);
Method 2: (pointer):
void MethodNMMS::tryNMSA(double* funcTry)
{
(*funcTry) = (*funcTry) + 1.0;
//...
}
// other initializations for funcEvals...
double funcTry = 0;
tryNMSA(&funcTry);
Make up your mind and use only one of them, it saves a great deal of confusion.
(actually, here you can use one more method - the return value). It's useful to put emphasis on this one value being main purpose of the function.
double MethodNMMS::tryNMSA(double funcTry)
{
//...
return funcTry + 1.0;
}
// other initializations for funcEvals...
double funcTry = 0;
funcTry = tryNMSA(funcTry);
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).