Can we assign values to function? - c++

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++.

Related

Behaviour of pass by reference and its scope

In the below code the variable a is passed to a constructor by reference, received by the parameter x. Then x is passed as a reference to an attribute. The attribute is then initialized with value 3. The program outputs the value 3 when running.
MY QUESTION
Shouldn't the program crash or show 2 because after the constructor is called
x should go out of scope and be released and its address should be freed right. and trying to write to it should give a memory access violation. However in this case the x is still in program control holding the address of 'a'
Is this valid c++ behavior or am i missing something?
#include <iostream>
#include <conio.h>
using namespace std;
class myclass {
public:
int& attribute;
myclass(int& x):attribute(x) {
}
void func() {
attribute = 3;
}
};
int main() {
int a = 2;
myclass obj(a);
obj.func();
std::cout << a;
_getch();
}
No this program is fine. attribute is a reference to a. The fact that x has gone out of scope is neither here nor there.
If you changed your code to
myclass(int x):attribute(x)
then that would be a problem.
The behavior of the program line by line
variable "a" is initialized with value 2
int a = 2;
Initialize obj with the variable a
myclass obj(a);
First x becomes the reference to a, then attribute becomes the reference to x. Consequently, attribute becomes the reference to a, which has the value 2 at the moment.
myclass(int& x):attribute(x) {}
Call func() of obj
obj.func();
attribute is the reference to a.
Both "attribute" and "a" are changed to 3. Consider them as the same,
single variable, just with difference alias.
That means, at this moment, attribute and a refers to the same variable,
and can be used interchangeably.
void func() {
attribute = 3;
}

What does the compiler do when encountering a return statement?

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 scope and lifetime of static local variable in c++

#include<iostream>
using namespace std;
int &fun()
{
static int x = 10;
return x;
}
int main()
{
fun() = 30;
cout << fun();
return 0;
}
when the above program is run,the output is 30.The integer variable x was returned,as a reference to the main() function and it is assigned the value of 30.But isn't the scope of x limited to the fun() function?;If so,why are we able to change the value of it in main function??
Scope is limited means any attempt to access x directly outside the scope is forbidden.
Within a scope, unqualified name lookup can be used to associate the
name with its declaration.
But you can always return a pointer or reference to this variable if variable is alive and you change it through that reference or pointer which points to the same variable. The name of this reference may be anonymous (temporary) or may be bound to some named reference.
About lifetime, it starts when the function containing static variable is called first time and ends when the program end.
Indeed the scope of x is limited to fun().
But because that function returns a reference to x, the caller (i.e. main) is able to modify x through that reference. That's what's happening here: x is set to 10 the first time the function is entered, but is changed to 30 by the assignment fun() = 30.

What does "int& foo()" mean in C++?

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! :)

Returning by value from a function - Why does it work?

Following is a simple function definition that returns an integer
int myFunc()
{
int localVar = 99;
return localVar;
}
and it called in main as
int main()
{
int y = myFunc();
cout << y << endl;
return 0;
}
This works as it is expected. I want to know why?
localVar is a local variable and its value is allocated in stack. It goes out of scope as soon as the function ends. So, localVar would have gone out of scope in the call int y = myFunc(); How/Why is it still able to return the correct value?
Your function is returning a copy of the value – that's what "return by value" means.
int y = myFunc(); will copy the bytes of the value from a temporary location used by the function invocation to your local variable.
It would only fail if you return the address of the local variable.
There are three things to be aware of here:
The object localVar
The return value of myFunc
The object y
Yes, localVar goes out of scope at the end of myFunc. However, before that happens, its value is being copied into the return value of myFunc (that's what the return statement does). Then, this return value is being copied into the object y. It doesn't matter that localVar is now gone - you have a copy of it.
That's exactly what returning by value does. It copies the result of the expression in the return statement into a return value.
localVar must not be generated on the stack. If a register is available it could be used also.
If it was in fact created on the stack then the value is copied to a register anyway on returning.
Because of the return type of your function: int myFunc(). It allows you to pass back an int value. The variable localVar is indeed out of scope in main(), but localVar is not being used there, y is, and when used as y = myFunc(), it accepts the int value returned.