#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.
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 just started on STRUCTURES, played with them a little and got burnt!
This is the 1st exhibition:
#include <iostream>
using namespace std;
struct structure1{
int h;
int m;
int s;
} structVar;
int func(structure1 x);
int main(){
structure1 x;
structVar.h=4;
structVar.m=6;
structVar.s=7;
func(structVar);
cout<<x.h<<x.m<<x.s<<endl;
}
int func(structure1 x){
--x.h;
--x.m;
--x.s;
};
Its output is:
1072276636-21953788778
But I expect:
356
So I tried this way, exhibition 2:
#include <iostream>
using namespace std;
struct structure1{
int h;
int m;
int s;
} structVar;
struct returnstruct{
int val1;
int val2;
int val3;
}returnvalue;
int func(structure1 x);
int main(){
structVar.h=4;
structVar.m=6;
structVar.s=7;
func(structVar);
cout<<returnvalue.val1<<returnvalue.val2<<returnvalue.val3<<endl;
}
int func(structure1 x){
returnvalue.val1=--x.h;
returnvalue.val2=--x.m;
returnvalue.val3=--x.s;
};
And got my required output:
356
Problem is I cant explain why
This confusion is mostly due to variable scoping.
Key points:
function parameter names, such as x, are local to the function. If a name conflict exists with a globally scoped variable, the local function parameter will take precedence.
structs are passed by value, which means a copy is made and passed to the function as the parameter.
Case 1, you have the structure definition for a struct called structure1. In this global scope you also have an instance of it, called structVar. Then inside the scope of the main function, you have defined a local variable of type structure1 called x. The following lines
structVar.h=4;
structVar.m=6;
structVar.s=7;
are modifying the global scoped variable, structvar. Then you call
func(structVar);
This line modifies a copy of the global variable, structVar by passing it in as a function parameter to func. func uses the name, x for its reference to a structure1, but remember, since structs are passed by value, this name is referring to a copy of whichever struct you pass to it between the parens - func(structVar). This parameter name, x, has no relationship to the other x defined in main. It is specific or scoped to the body of the function, func.
You can explore this a bit, by changing the name of the function parameter to y, and first notice that it will not compile, complaining about x being undefined. This means that within the body of that function, it doesn't know about the x you've defined in main because that x is local aka scoped only to main. Contrast this with structVar, which is defined outside of any function's parameter list or body. structVar can be referred to within either of the functions because its scope is global.
cout<<x.h<<x.m<<x.s<<endl;
Using this understanding of scope, this line then can be seen to operating on the x defined in main which has not had its members (h,m,s) initialized or assigned any values, thus the 'weird' output.
Now, let's look at the second block of code you posted.
Here, you've added another global scope struct, called returnvalue. Now, you have two global scope variables, structVar and returnvalue. Because of that scope, structVar is visible inside of main, where you are modifying its member values (h,m,s).
Next, you are passing that global variable to func as its parameter, x. Remember, this is making a copy of structVar, which func calls x. So, x has the values of structVar's h, m, and s.
Inside of func, because of that global scope, it can see returnValue. Using the copy of structVar, again now called x, you are setting the values of returnvalue to the (pre)decremented (--) values of the parameter x. Since x is a copy of structVar and structVar had its members set to the numbers h=4, m=6, s=7, returnvalue then receives h=3, m=5, s=6. func then returns back to main.
Now, back in main, since returnvalue is global scope, main can see it and print out its values using cout, thus the output of 356
The value of structure1 x is passed by value. That means that the func function gets a copy of the argument that the caller never sees. So func can have no effect in this context unless it returns something.
You can either return the modified structure of pass x by reference, e.g., structure1& x. In the latter case x refers to the object that the function was called with.
#include <iostream>
using namespace std;
struct structure1{
int h;
int m;
int s;
} structVar;
int func(structure1 x);
int main(){
structure1 x;
structVar.h=4;
structVar.m=6;
structVar.s=7;
func(structVar);
I changed the line below
cout<<structVar.h<<structVar.m<<structVar.s<<endl;
}
I changed the function below too
int func(structure1 x){
--structVar.h;
--structVar.m;
--structVar.s;
};
Output is 356 as expected
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.
typedef double real8;
typedef real8 Real_t;
Real_t& x(int y);
What is Real_t& ?? I've only seen a datatype followed by "&" to indicate pass by reference.
But this is in declaration line. What does this mean ?
This means that the function returns a reference to a Real_t which is actually a double. The Real_t is a real8 which is a double if you resolve all the typedefs.
You should be careful here. If the result being passed by reference isn't retrieved from a scope that exists pasts the end of the function, then you'll have a dangling reference.
For example:
int& foo() {
int x = 8;
return x;
}
int main() {
int y = foo();
}
The variable, y, in main ends up referring to a variable which has been destroyed as it went out of scope when foo() returned, so using it is undefined behavior. If x had been retrieved from a singleton or something that lives outside the scope of the function foo(), then it would still exist though and this would be fine.
People sometimes return references to initialize static globals in a deterministic way between compilation units, so you might see this used with statics like:
MyClass& MyStaticVar() {
static MyClass instance;
return instance;
}
Which is also okay, because the static lives for the duration of the program after initialized.
It means x is a function that returns a reference to a Real_t.
An example of returning by reference is for data access in classes. For example, std::vector::at() returns a reference to an element of the vector.
For a free function to safely return a reference, there must be something non-obvious going on inside the function to ensure that a dangling reference isn't returned.
Could someone exactly explain the concept of scope and life of variable in C. Is it different in C++? I'm confused between scope and life.
"Scope" of a variable is a region of source code, where you can refer to that variable.
"Lifetime" is how long it exists during the program execution.
By default the lifetime of a local variable is the same as its scope:
void foo()
{
int x = 123;
cout << x << endl;
x += 1;
}
int main(){ foo(); foo(); foo(); }
Here, each time foo is called a new x is created (space is reserved for it on the stack), and when the execution leaves the block where x was declared, x is destroyed (which for int just means that the space that was reserved, now is freed for reuse).
In contrast:
void foo()
{
static int x = 123;
cout << x << endl;
x += 1;
}
int main(){ foo(); foo(); foo(); }
Here, since x is declared static, space is reserved for x before the program execution even begins. x has a fixed location in memory, it's a static variable. And C++ has special rules about the initialization of such a variable: it happens the first time the execution passes through the declaration.
Thus, in the first call of foo this x is initialized, the output statement displays 123, and the increment increases the value by 1. In the next call the initialization is skipped (it has already been performed), the value 124 is output, and the value is incremented again. So on.
The lifetime of this x is from start of execution to end of execution.
Scope is the region where the variable is accessible.
Life time is the time span during which an object remains valid.
An simple example:
#include <iostream.h>
void doSomething()
{
x = 5; //Error! Not Accessible
}
int main()
{
int x = 4;
std::cout<< x << endl;
{
int x = 2;
cout << x << endl;
}
doSomething();
std::cout<< x << endl;
return 0;
}
The above gives the output:
4
2
4
In above program,
lifetime of variable x = 4 is throughout the main, i.e: It remains alive throughout the execution of the main, Also it is accessible within the main, that is its scope. Note that it is not accessible in the function because it is beyond the scope of the variable x.
while scope and lifetime of variable x = 2 is within the enclsing braces{ } inside the main.
The scope of a variable is determined at compilation time. It is the region in the program where the same object that is defined through the definition is accessible through that identifier.
The lifetime of an object is a feature that is defined at runtime, through the flow of execution. An object can be accessed through a pointer even if the variable through which it was defined is not in scope.
void f(char *a) {
*a = 'f';
}
void g(void) {
char aChar = ' ';
f(&aChar);
}
Here the scope of variable aChar (the identifier) is the body of g. During the execution of g the lifetime of the object expands to the execution of f. Using the identifier aChar inside f would be illegal, the compiler would tell you something like "unknown indetifier aChar in function f". Using a pointer to that object as done above is completely legal.
The scope of a variable refers to the extent to which different parts of a program have access to the variable.
Variables can be declared as:
Inside a function which is called local variables or internal variables.
Outside of all functions which is called global variables or external variables and lifetime or "extent" extends across the entire run of the program.
Here is detailed tutorial about variables with examples : What is variable in C