While reading this explanation on lvalues and rvalues, these lines of code stuck out to me:
int& foo();
foo() = 42; // OK, foo() is an lvalue
I tried it in g++, but the compiler says "undefined reference to foo()". If I add
int foo()
{
return 2;
}
int main()
{
int& foo();
foo() = 42;
}
It compiles fine, but running it gives a segmentation fault. Just the line
int& foo();
by itself both compiles and runs without any problems.
What does this code mean? How can you assign a value to a function call, and why is it not an rvalue?
The explanation is assuming that there is some reasonable implementation for foo which returns an lvalue reference to a valid int.
Such an implementation might be:
int a = 2; //global variable, lives until program termination
int& foo() {
return a;
}
Now, since foo returns an lvalue reference, we can assign something to the return value, like so:
foo() = 42;
This will update the global a with the value 42, which we can check by accessing the variable directly or calling foo again:
int main() {
foo() = 42;
std::cout << a; //prints 42
std::cout << foo(); //also prints 42
}
All the other answers declare a static inside the function. I think that might confuse you, so take a look at this:
int& highest(int & i, int & j)
{
if (i > j)
{
return i;
}
return j;
}
int main()
{
int a{ 3};
int b{ 4 };
highest(a, b) = 11;
return 0;
}
Because highest() returns a reference, you can assign a value to it. When this runs, b will be changed to 11. If you changed the initialization so that a was, say, 8, then a would be changed to 11. This is some code that might actually serve a purpose, unlike the other examples.
int& foo();
Declares a function named foo that returns a reference to an int. What that examples fails to do is give you a definition of that function that you could compile. If we use
int & foo()
{
static int bar = 0;
return bar;
}
Now we have a function that returns a reference to bar. since bar is static it will live on after the call to the function so returning a reference to it is safe. Now if we do
foo() = 42;
What happens is we assign 42 to bar since we assign to the reference and the reference is just an alias for bar. If we call the function again like
std::cout << foo();
It would print 42 since we set bar to that above.
int &foo(); declares a function called foo() with return type int&. If you call this function without providing a body then you are likely to get an undefined reference error.
In your second attempt you provided a function int foo(). This has a different return type to the function declared by int& foo();. So you have two declarations of the same foo that don't match, which violates the One Definition Rule causing undefined behaviour (no diagnostic required).
For something that works, take out the local function declaration. They can lead to silent undefined behaviour as you have seen. Instead, only use function declarations outside of any function. Your program could look like:
int &foo()
{
static int i = 2;
return i;
}
int main()
{
++foo();
std::cout << foo() << '\n';
}
int& foo(); is a function returning a reference to int. Your provided function returns int without reference.
You may do
int& foo()
{
static int i = 42;
return i;
}
int main()
{
int& foo();
foo() = 42;
}
int & foo(); means that foo() returns a reference to a variable.
Consider this code:
#include <iostream>
int k = 0;
int &foo()
{
return k;
}
int main(int argc,char **argv)
{
k = 4;
foo() = 5;
std::cout << "k=" << k << "\n";
return 0;
}
This code prints:
$ ./a.out
k=5
Because foo() returns a reference to the global variable k.
In your revised code, you are casting the returned value to a reference, which is then invalid.
In that context the & means a reference - so foo returns a reference to an int, rather than an int.
I'm not sure if you'd have worked with pointers yet, but it's a similar idea, you're not actually returning the value out of the function - instead you're passing the information needed to find the location in memory where that int is.
So to summarize you're not assigning a value to a function call - you're using a function to get a reference, and then assigning the value being referenced to a new value. It's easy to think everything happens at once, but in reality the computer does everything in a precise order.
If you're wondering - the reason you're getting a segfault is because you're returning a numeric literal '2' - so it's the exact error you'd get if you were to define a const int and then try to modify its value.
If you haven't learned about pointers and dynamic memory yet then I'd recommend that first as there's a few concepts that I think are hard to understand unless you're learning them all at once.
The example code at the linked page is just a dummy function declaration. It does not compile, but if you had some function defined, it would work generally. The example meant "If you had a function with this signature, you could use it like that".
In your example, foo is clearly returning an lvalue based on the signature, but you return an rvalue that is converted to an lvalue. This clearly is determined to fail. You could do:
int& foo()
{
static int x;
return x;
}
and would succeed by changing the value of x, when saying:
foo() = 10;
The function you have, foo(), is a function that returns a reference to an integer.
So let's say originally foo returned 5, and later on, in your main function, you say foo() = 10;, then prints out foo, it will print 10 instead of 5.
I hope that makes sense :)
I'm new to programming as well. It's interesting to see questions like this that makes you think! :)
Related
Why the output is 30 here? And how fun()=30 is valid? What is meant by assigning function a value? And why removing static keyword throws segmentation fault?
#include<iostream>
using namespace std;
int &fun()
{
static int x = 10;
return x;
}
int main()
{
fun() = 30;
cout << fun();
return 0;
}
Let's walk through your program step by step:
inside main() fun() is called.
fun() has a static variable x (static means, that x is stored in a special part of memory and not on the stack, so its value is preserved between function calls) (It's like having a global variable that is only visible from inside fun())
fun() returns a reference to x (references are almost like pointers)
You write to the returned reference of x, so x actually gets changed! (You don't write to the function)
now x is 30 and fun() returns 30 on the next call.
I hope this answers your first three questions.
Why you get a segmentation fault without the static keyword:
In this case x does exist on the stack. So whenever you call fun() some memory gets allocated on the stack to hold x. When fun() returns, this memory will be deallocated.
Now, the reference returned by fun(), will reference a piece memory, that is not allocated by your program anymore. In other words, the returned reference will reference a memory address, that does "not belong to your program", thus you are not allowed to write to it. And so you get a segmentation fault.
Can we assign values to function:
To answer the actual title of your question: Yes, we can, using function pointers:
int foo(int x) {
return x + 1;
}
int bar(int x) {
return x * 2;
}
void main() {
int(*f)(int) = foo;
// int the function pointed to returns an int
// (*f) f is the name of the function pointer
// (int) the function pointed to takes on int as paramter
// = foo; f now points to the function foo()
(*f)(3); // the same as foo(3), returns 4
f = bar; // now f points to bar()
(*f)(3); // the same as bar(3), returns 6
}
fun() returns a reference to static variable x, to which you assign the value 30. You don't assign anything to the function itself. In fact, it is not possible to assign anything to a function in C++.
I have this code:-
int i;
class A
{
public:
~A()
{
i = 10;
}
};
int& foo()
{
i = 3;
A ob;
return i;
}
int main()
{
cout << "i = " << foo() << endl; //call to foo
return 0;
}
I'm confused about the order in which the compiler executes this code after encountering the return i statement.
My guess:
A variable of the caller(main) is made(say K) and a reference to it is passed to foo(), when the return statement is encountered, the compiler copies the value of the return statement into K, in this case the address of i, as a reference is being returned. Then it jumps to the end of foo() and the destructor for class object ob is called which changes the value of i to 10. This is followed by the removal of foo() and all its variables(including the reference to K passed to foo) from the call stack and the control is returned to main where K replaces the call to foo() and the cout is implemented.
Is this the correct order of actions taken by the compiler ?
I searched extensively for what happens in memory when a return is called and this was the best result, though it is for C#.
The function foo is in scope any place inside this source file, so there's no problem calling it.
As for the reference it's returning, i is a file scope variable and thus has static storage duration, which means its lifetime is the life of the program. This means you're allowed to return a reference to it from foo.
Had you attempted to return a reference to a local variable like this:
int& foo()
{
int x = 3;
return x;
}
That would invokes undefined behavior since the variable no longer exists after the function exits.
The usual way to pass a variable by reference in C++(also C) is as follows:
void _someFunction(dataType *name){ // dataType e.g int,char,float etc.
/****
definition
*/
}
int main(){
dataType v;
_somefunction(&v); //address of variable v being passed
return 0;
}
But to my surprise, I noticed when passing an object by reference the name of object itself serves the purpose(no & symbol required) and that during declaration/definition of function no * symbol is required before the argument.
The following example should make it clear:
// this
#include <iostream>
using namespace std;
class CDummy {
public:
int isitme (CDummy& param); //why not (CDummy* param);
};
int CDummy::isitme (CDummy& param)
{
if (¶m == this) return true;
else return false;
}
int main () {
CDummy a;
CDummy* b = &a;
if ( b->isitme(a) ) //why not isitme(&a)
cout << "yes, &a is b";
return 0;
}
I have problem understanding why is this special treatment done with class . Even structures which are almost like a class are not used this way. Is object name treated as address as in case of arrays?
What seems to be confusing you is the fact that functions that are declared to be pass-by-reference (using the &) aren't called using actual addresses, i.e. &a.
The simple answer is that declaring a function as pass-by-reference:
void foo(int& x);
is all we need. It's then passed by reference automatically.
You now call this function like so:
int y = 5;
foo(y);
and y will be passed by reference.
You could also do it like this (but why would you? The mantra is: Use references when possible, pointers when needed) :
#include <iostream>
using namespace std;
class CDummy {
public:
int isitme (CDummy* param);
};
int CDummy::isitme (CDummy* param)
{
if (param == this) return true;
else return false;
}
int main () {
CDummy a;
CDummy* b = &a; // assigning address of a to b
if ( b->isitme(&a) ) // Called with &a (address of a) instead of a
cout << "yes, &a is b";
return 0;
}
Output:
yes, &a is b
A reference is really a pointer with enough sugar to make it taste nice... ;)
But it also uses a different syntax to pointers, which makes it a bit easier to use references than pointers. Because of this, we don't need & when calling the function that takes the pointer - the compiler deals with that for you. And you don't need * to get the content of a reference.
To call a reference an alias is a pretty accurate description - it is "another name for the same thing". So when a is passed as a reference, we're really passing a, not a copy of a - it is done (internally) by passing the address of a, but you don't need to worry about how that works [unless you are writing your own compiler, but then there are lots of other fun things you need to know when writing your own compiler, that you don't need to worry about when you are just programming].
Note that references work the same way for int or a class type.
Ok, well it seems that you are confusing pass-by-reference with pass-by-value. Also, C and C++ are different languages. C doesn't support pass-by-reference.
Here are two C++ examples of pass by value:
// ex.1
int add(int a, int b)
{
return a + b;
}
// ex.2
void add(int a, int b, int *result)
{
*result = a + b;
}
void main()
{
int result = 0;
// ex.1
result = add(2,2); // result will be 4 after call
// ex.2
add(2,3,&result); // result will be 5 after call
}
When ex.1 is called, the constants 2 and 2 are passed into the function by making local copies of them on the stack. When the function returns, the stack is popped off and anything passed to the function on the stack is effectively gone.
The same thing happens in ex.2, except this time, a pointer to an int variable is also passed on the stack. The function uses this pointer (which is simply a memory address) to dereference and change the value at that memory address in order to "return" the result. Since the function needs a memory address as a parameter, then we must supply it with one, which we do by using the & "address-of" operator on the variable result.
Here are two C++ examples of pass-by-reference:
// ex.3
int add(int &a, int &b)
{
return a+b;
}
// ex.4
void add(int &a, int &b, int &result)
{
result = a + b;
}
void main()
{
int result = 0;
// ex.3
result = add(2,2); // result = 2 after call
// ex.4
add(2,3,result); // result = 5 after call
}
Both of these functions have the same end result as the first two examples, but the difference is in how they are called, and how the compiler handles them.
First, lets clear up how pass-by-reference works. In pass-by-reference, generally the compiler implementation will use a "pointer" variable in the final executable in order to access the referenced variable, (or so seems to be the consensus) but this doesn't have to be true. Technically, the compiler can simply substitute the referenced variable's memory address directly, and I suspect this to be more true than generally believed. So, when using a reference, it could actually produce a more efficient executable, even if only slightly.
Next, obviously the way a function is called when using pass-by-reference is no different than pass-by-value, and the effect is that you have direct access to the original variables within the function. This has the result of encapsulation by hiding the implementation details from the caller. The downside is that you cannot change the passed in parameters without also changing the original variables outside of the function. In functions where you want the performance improvement from not having to copy large objects, but you don't want to modify the original object, then prefix the reference parameters with const.
Lastly, you cannot change a reference after it has been made, unlike a pointer variable, and they must be initialized upon creation.
Hope I covered everything, and that it was all understandable.
Passing by reference in the above case is just an alias for the actual object.
You'll be referring to the actual object just with a different name.
There are many advantages which references offer compared to pointer references.
One thing that I have to add is that there is no reference in C.
Secondly, this is the language syntax convention.
& - is an address operator but it also mean a reference - all depends on usa case
If there was some "reference" keyword instead of & you could write
int CDummy::isitme (reference CDummy param)
but this is C++ and we should accept it advantages and disadvantages...
This question already has answers here:
Closed 11 years ago.
foo(int &bar)
{
bar = 5;
}
The call to this function would be
int foobar = 2;
foo(foobar);
Am I right in thinking that the function parameter essentially 'gets' the memory address of the variable, but does not then have to be dereferenced in foo, and that I would be changing the original value of foobar? Before this I was under the Impression that you would have to pass in a memory address like this:
foo(&foobar);
and then use the variable inside foo like this:
*bar = 5;
Am I right in thinking that this is wrong? I think, like a lot of beginners, the confusion came from thinking that a reference was like a pointer in that it held a memory address, but it's never really a type is it? Just an operator.
References are usually implemented with underlying pointers (although that is not mandated by the standard), but they are a totally different beast than pointers. A reference is simply a new name or alias for an existing variable. When you do
void foo(int& bar)
{
bar = 5;
}
int foobar = 2;
foo(foobar);
you are invoking foo to be evaluated with the variable foobar, so essentially bar within foo becames foobar. The usual compiler impementation for this is to actually implement this code like this:
void foo(int* bar)
{
*bar = 5;
}
int foobar = 2;
foo(&foobar);
If you did this:
void foo(int& bar) { bar = 6; }
int main() {
int x = 3;
foo(x);
}
x in main would equal 6. This is because a reference/alias (a different name for the same variable) is passed into foo. So, bar in function foo is the same variable as x in main, same memory location, and everything.
This is different from normal passing like this:
void foo(int bar) { bar = 6; }
int main() {
int x = 3;
foo(x);
}
where bar would be a new copy constructed value copied from x in main (note that copy constructor would better apply to a non-scalar type, but the idea is the same).
And lastly, if you did:
void foo(int* bar) { *bar = 6; }
int main() {
int x = 3;
foo(&x);
}
It would say "I want a pointer to an integer" for foo's parameter. In main, we take the "Address of stack variable x" which is in essence the same thing as a pointer to x, and we pass it into bar. Then dereferencing bar and assigning 6 to it would make x in main equal to 6 too :)
I got the answer NO! Because passing by value and passing by reference looks identical to the caller.
However, the code below compiles right
class A {
public:
void f(int i) {}
void f(int& i) {}
};
But when I try to use it, there is compile error.
int main () {
A a;
int i = 9;
int& j = i;
a.f(1);
a.f(i);
a.f(j);
return 0;
}
Why does not the compiler disable it even without knowing it is going to be used?
You can call each method:
void (A::*t)(int& ) =&A::f;
A a;
int i = 9;
int& j = i;
a.f(1); // f(int i)
(a.*t)(i); // f(int& i)
Yes, they can be overloaded based on reference or not. That is why it's perfectly fine to have them coexist like that; they are different.
The problem has to do with ambiguity. While f(1) can only be called on one variation, f(i) can be called on both. Neither is preferable, therefore you get an error for ambiguity. If you added a third function, foo (const int&), all calls would be ambiguous. But all are still overloads of each other, and non-conflicting.
I agree it's strange to be able to have three overloads of a function, and be able to directly call none. Perhaps someone else has more to add.