static const cached result - c++

In the following example -
#include <iostream>
int someMethod(){
static int a = 20;
static const int result = a + 1;
++a;
std::cout << " [" << a << "] ";
return result;
}
int main(){
std::cout << someMethod() << "\n";
std::cout << someMethod() << "\n";
std::cout << someMethod() << "\n";
}
The output comes as -
[21] 21
[22] 21
[23] 21
What is the reason that is preventing result value to be modified on subsequent calls made to the same function? I've printed the output of variable a as well, which is certainly being incremented and since it is static as well there must not be multiple copies existing for the same method.
IDEONE - COMPILER OUTPUT

The const here only disturb the reader from the real cause. This code performs exactly the same.
int someMethod(){
static int a = 20;
static int result = a + 1;
++a;
std::cout << " [" << a << "] ";
return result;
}
The real reason is that the = sign can represent two different operations in C++: an assignation (executed each time) or an initialisation (executed only when the variable is created). The difference in when it is part of declaration/definition of the variable.
In normal context (not bloc static variables), both are equivalent because an automatic variable is created every time the block in which it is declared it run (or at least the compiler must ensure that all behaves as if it that the case).
But for a block static variable the initialization occurs only once and here the variable result is initialized to 21 and its value will never change.
Those variants would be much different
int someMethod(){
static int a = 20;
static int result;
result = a + 1; // assignation: result will see its value change with the value of a
...
int someMethod(){
static int a = 20;
static const int result = a;
result = a + 1; // Error modification of a const declared variable

Since result is static, it will be initialized only once during runtime.Therefore the following line is executed only once no matter how many times you call someMethod()
static const int result = a + 1;

Static is a hint to the compiler not to reinitialize a variable aside from forcing the compiler to allocate the variable's value on the program's data segment.

As explained by others, result is a static variable so it's initialized only at the first execution of someMethod().
And result is also const, so the first value assigned with
static const int result = a + 1;
remain unmodified for the following execution of the program.
I suppose you were expecting something that is achievable using a reference; if you modify the preceding line as follows
static const int & result = a;
^
// note the & ---|
you link result to a and modifying a you modify result and the output is
[21] 21
[22] 22
[23] 23
The problem is that you can reference a variable to another variable, not to an expression; so you can link result to a, not to a+1 (not to the dynamic value of a+1); so the following line
static const int & result = a + 1;
compile but (if I'm not wrong) link result to the unnamed variable where is stored (at the first execution of someMethod()) the result of the expression a + 1, so the output is again
[21] 21
[22] 21
[23] 21

Related

I don't understand a part of the C++ code, can someone explain it?

I was wondering if someone could explain why the f2(a,a); is 13 13 and not 12 12?
Does this have something to do with the & sign, if so what does it mean?
Thanks in advance!
#include <iostream>
using namespace std;
void f1 (int a, int b){
a = 12; b = 13;
}
void f2 (int& a, int& b){
a = 12; b = 13;
}
int main()
{
int a = 10; int b = 11;
f1(a,b);
cout << a << ' ' << b << ' ';
f2(a,b);
cout << a << ' ' << b << ' ';
f2(a,a);
cout << a << ' ' << b;
}
In your call f2(a, a) both arguments refer to the same variable (a) (the ampersand means "reference") so that is all you are changing. The function first assign 12 to it, then you assign 13 to it - so that's the final value. The variable b in the main function is not changed by that function call and retains its value (13), so when you subsequently print a and b in main, you get 13 and 13.
This function
void f2 (int& a, int& b){
a = 12; b = 13;
}
accepts its arguments by reference. So calling it like
f2(a,a);
the both parameters are references to the same object a.
At first this object was assigned with the value 12
a = 12;
and then reassigned with the value 13
b = 13;
So the resulting value of the referenced object a is 13.
To make it more clear you can imagine the function call and its definition the following way (I will rename the parameters as a1 and b1 to avoid name collision)
f2(a,a);
// ...
void f2 ( /* int& a1, int& b1 */ ){
int &a1 = a;
a1 = 12;
int &b1 = a;
b1 = 13;
}
So the object a is being changed through the reference to it a1 and b1.
That is you may declare several references to the same object and use the references in any order to change the referenced object. The object will contain the last value assigned to it through one of the references.
Pay attention to that before this call
f2(a,a);
there was the following call
f2(a,b);
that set the value of the variable b to 13.
So this statement after the above two calls
cout << a << ' ' << b;
outputs
13 13
By assigning a to f2(a,a); as both parameters you are doing so as a reference parameter and your code is executed sequentially. So a is first given the value 12 (the value assigned to formal parameter a in the function) and then the same variable is given the value 13 (the value assigned to formal parameter b in the function). The variable b in the main part of your program was is 13 after the function call f2(a,b);.

Returning a C++ reference variable VS returning a variable

Assume the following function in C++:
#include <iostream>
int& change(int& a){
a = 6;
return a;
}
int main(){
int a = 5;
int b = change(a);
std::cout << b << std::endl;
return 0;
}
Running this will return:
6
My question is, if I change the return type from int& to int, compiler won't complain and it will still print 6. So how does retuning a reference work in C++? (comparing it with returning a pointer in C)
Reference, like a pointer is implemented by storing the address of an object.
Returning by Value means that it is returning a copy of the old object.
Returning by Reference means that it is returning the address of the old object.
#include <iostream>
int& change_ref(int& a) {
a = 6;
return a;
}
int change_value(int& a) {
a = 6;
return a;
}
int main() {
int a = 5;
change_ref(a) = 7;
// change_value(a) = 7; compile error
std::cout << a << std::endl;
int& a1 = change_ref(a); // return reference of a
// now a1 ref the a
a1 = 10;
// print a = 10 and a1 = 10
std::cout << a << " " << a1 << std::endl;
int a2 = change_value(a); // return a value of a, so return is 6
// value of a is 6 and define a new value a2
a2 = 11;
// set a2 to 11 and not change a
// print a = 6, a1=6, a2= 11
std::cout << a << " " << a1 << " " << a2 << std::endl;
return 0;
}
You can return by reference as long as it isn't a locally declared variable (as those would be removed from the stack). Returning by reference just means that it is not returning a copy of the object but the actual object.
You are calling the function change() by reference and then updating the actual value of a to 6. Since the value of a updated to 6, so irrespective of return type a will carrying the updated value and always print 6 in the given example.
NOTE: Declared data of b is int, hence you are not printing any reference.

Returning 0 after functions are called without "return(0);"

I'm having a small issue in trying to figure out why a zero is printed out at the end of my while loop.
#include <iostream>
using namespace std;
int x;
int CountDown(int x);
int CountUp(int x);
int main()
{
int toCountUp = CountUp(x);
cout << x << endl;
}
int CountUp(int x)
{
x = 0;
while(x <= 10)
{
cout << x << endl;
x++;
}
}
My best response would be that it is in the condition of the while loop. Or a return status from the function/main being fulfilled, but I don't have a return on there, and I know a function doesn't require a return statement but in this while loop I want there to be a integer returned, do I need to make the function void so there will be no return? But what about the parameter x that I need for the while loop?
code output:
0
1
2
3
4
5
6
7
8
9
10
0 < ---- this is the number I do not want.
Thinking about it, it has to be a value returned at the end of the function, any ideas?
This outputs the values 0 through 10:
int toCountUp = CountUp(x);
Then, this outputs 0:
cout << x << endl;
The method does not change the value that is passed to it, it uses its own local copy of that variable.
—It's mainly because you are printing cout << x << endl; twice. Once in the int CountUp(int x) function itself, but again in the main function.
—It could've printed any given value of x at this point, but since you're setting x=0 outside of the While{} loop in the int CountUp(int x) function, it's printing 0 at the end after the function call is executed.
*int CountUp(int x)
{
x = 0;
while(x <= 10)
{
cout << x << endl;
x++;
}
}*
—Is there a reason why you are setting x=0 within the function? since you're passing x as a parameter in the function call, and adding 1 to it in the While{} loop until it's x<= 10? Asking because you're not returning x back to the main() function.
—In case you wanted to use the end value of x to countdown using CountDown(x), you may like to reset x=0 in the main() function after calling the block—
*int CountUp(int x)
{
x = 0;
while(x <= 10)
{
cout << x << endl;
x++;
}
}*
At last 0 is printed in main() function because x is declared global.
If you want latest x after loop got over to be printed in main() then you should reference variable and don't declare it globally.
int CountUp(int &); /* function prototype*/
Since passed variable(actual argument) and reference variable having the same memory So modification will affects in calling function.
int CountUp(int &x) { /* catch with reference variable so that modification affects in calling function also */
x = 0;
while(x <= 10)
{
cout << x << endl;
x++;
}
}
First read Shadowing variables and What's the difference between passing by reference vs. passing by value?
The int x parameter of CountUp shadows the global variable int x so inside CountUp, the only x is the parameter.
int CountUp(int x)
int x defines x as passed by value, so it is a copy of the x used to call CountUp in main. This different x is counted up to 10 and then discarded.
the global int x has static storage duration and is default initialized to zero for you. Do not try this trick with a variable with Automatic duration because unless it has a constructor that does something useful, the contents are uninitialized and their value is undefined.
Sideshow issue:
A function that has a non-void return type MUST return a value on ALL paths. If it does not, you have Undefined Behaviour and the compiler can generate hopelessly invalid code that can get you even if the bad path is not taken. Don't smurf with Undefined Behaviour, as it might crash the program or do something hilariously wrong, but it might also look like it works until it suddenly doesn't at a really bad time.
Solutions:
void CountUp(int & x)
{
x = 0;
while(x <= 10)
{
cout << x << endl;
x++;
}
}
Passes x by reference allowing global x and the local x to be one and the same and returns nothing.
Usage would be
CountUp(x);
Not so useful in the asker's case because it doesn't leave a toCountUp.
int CountUp(int x)
{
x = 0;
while(x <= 10)
{
cout << x << endl;
x++;
}
return x;
}
Makes a copy if the provided x, operates on the copy, and then returns x. Usage would be
int toCountUp = CountUp(x);
And will set toCountUp to 10 higher than the global x.

Why does the function always refer to one specific parameter?

In the following code:
int sum(int a=40, int b=20)
{
int result;
result = a + b;
return (result);
}
int main ()
{
int a = 100;
int b = 200;
int result;
result = sum(a, b);
cout << "Total value is :" << result << endl;
result = sum(a);
cout << "Total value is :" << result << endl;
return 0;
}
This produces:
Total value is : 300
Total value is : 120
Why does the:
sum(a)
add the (int a) in the 2nd block to the (int b) in the 1st block?
Im confused why the (b) value in the 1st block is used in (sum(a)), but the (a) value in the 1st block is ignored.
int sum(int a=40, int b=20) {
...
}
declares the parameters a to be 40 and b to be to 20, if not specified. This is a compiler service, so sum(a) becomes sum(a, 20) (b not specified). Similar to this, sum() becomes sum(40, 20). a and b in your method sum are default parameters.
In function sum you are using default arguments. That's why when you call
result = sum(a); // where a = 100 and the second parameter is ommited
in the function sum, the first parameter is take the value of this caller's a (= 100), and as the second parameter is absent from the caller's end, the default b (= 20) will be used as b. Hence the result is
100 + 20
= 120
As David Rodríguez suggested in the first comment, use different variables name (say sum (int x, int y)) for no ambiguity and better understanding.
In order to make it shorter:
int sum(int a=40, int b=20)
{
return a + b;
}
int main ()
{
int a = 100;
int b = 200;
cout << "Total value is :" << sum(a, b) << endl;
cout << "Total value is :" << sum(a) << endl;
return 0;
}
In the sum(a,b) both of the parameters have values => it does a+b => 100 + 200 which is 300.
In the sum(a) the second parameter is not set, the function use the default value (ie: 20) => a + 20 => 100 + 20 which is 120
The a & b you define in your main are not the one of the sum function
Well, you should read a bit about default parameters in C++. Where you are on it, I recommend you to research a bit about overloading, since they are somewhat related.
On the first call you do to the sum() function, you provide both parameter to the call, so the variables a and b ,that you declared, are used, hence you get 100+200=300. On the second call tho, you only provide one parameter, so the second one uses the default parameter value, i.e. a=100, b gets the default value (20), so you get 100+20=120.
When you write a function like
returntype Function_name(data_type some_value), then this is called default parameters.
For eg: if you write a function like,
int calculate_area(int lenght=20, int width=25)
Then when you call this function from main, you can either pass values to length and width like this,
int main() {
int a=50;
int b=60;
calculate_area(a,b);
}
Or you can call it like this...
int main() {
calculate_area();
}
See the difference, we are not passing any parameter, still it is a valid call to the function, because in this case.... the default values mentioned by you for length and width will be considered, which in this case is 20 & 25.
And about variables 'a' & 'b' in your code, looks like you are getting confused between name of the variables. Main() and Sum() are two different functions.
'a' of sum has nothing to do with 'a' of main. You will understand this when you will read how the variables are stored in stack and all.

Where and how are constants stored?

I read this question from here and I also read related question from c-faq but I don't understand the exact reason behind this :-
#include <iostream>
using namespace std;
int main()
{
//const int *p1 = (int*) &(5); //error C2101: '&' on constant
//cout << *p1;
const int five = 5;
const int *p2 = &(five);
cout << *p2 << endl;
char *chPtr = (char*) &("abcde");
for (int i=0; i<4; i++) cout << *(chPtr+i);
cout << endl;
return 0;
}
I was wondering how constants, either integer or string literal, get stored. My understanding of string literals is that they are created in global static memory upon start of program and persist until program exit. In the case of "abcde" even though I did not give it a variable name I can take it's address (chPtr) and I assume I could probably dereference chPtr any time before program termination and the character values would still be there, even if I dereferenced it outside the scope where it was declared. Is the const int variable "five" also placed in global static and that address p2 can also be referenced any time?
Why can I take the address of "five" but I cannot ask for: &(5) ? Are the constants "5" and "five" stored differently? and where "5" is get stored in memory ?
You cannot take the address of a literal (e.g. &(5)) because the literal is not "stored" anywhere - it is actually written in the assembly instruction. Depending on the platform, you'll get different instructions, but a MIPS64 addition example would look like this:
DADDUI R1, R1, #5
Trying to take the address of the immediate is meaningless as it doesn't reside in (data) memory, but is actually part of the instruction.
If you declare a const int i = 5, and do not need the address of it, the compiler can (and likely will) convert it to a literal and place 5 in the appropriate assembly instructions. Once you attempt to take the address of i, the compiler will see that it can no longer do that, and will place it in memory. This is not the case if you just attempt to take the address of a literal because you haven't indicated to the compiler that it needed to allocate space for a variable (when you declare a const int i, it allocates the space in the first pass, and will later determine it no longer needs it - it does not function in the reverse).
String constants are stored in the static portion of the data memory - which is why you can take the address of them.
"It depends" is probably not a satisfying answer, but it is the correct one. The compiler will store some const variables in the stack if it needs to (such as if you ever take the address of it). However, there has always been the idea of a "constexpr" variable in compilers, even if we didn't always have the mechansim to call it directly: If an expression can be calculated at compile time, then instead of caluclating it at run time, we can calculate it durring compile time. And if we can calculate it at compile time, and we never do anything that requires it to be something different, then we can remove it all together and turn it into a literal, which would be part of the instruction!
Take for example, the following code:
int main(int argc, char** argv)
{
const int a = 2;
const int b = 3;
const int c = a+b;
volatile int d = 6;
volatile int e = c+d;
std::cout << e << std::endl;
return 0;
}
Look at how smart the compiler is:
37 const int a = 2;
38 const int b = 3;
39 const int c = a+b;
40
41 volatile int d = 6;
0x400949 <+0x0009> movl $0x6,0x8(%rsp)
42 volatile int e = c+d;
0x400951 <+0x0011> mov 0x8(%rsp),%eax
0x400955 <+0x0015> add $0x5,%eax
0x400958 <+0x0018> mov %eax,0xc(%rsp)
43
44 std::cout << e << std::endl;
0x400944 <+0x0004> mov $0x601060,%edi
0x40095c <+0x001c> mov 0xc(%rsp),%esi
0x400960 <+0x0020> callq 0x4008d0 <_ZNSolsEi#plt>
45 return 0;
46 }
(volatile tells the compiler not to do fancy memory tricks to that variable) In line 41, when I use c, the add is done with the LITERAL 0x5, despite it even be a combination of the other code. Lines 37-39 contain NO instructions.
Now lets change the code so that I need the location of a:
int main(int argc, char** argv)
{
const int a = 2;
const int b = 3;
const int c = a+b;
volatile int d = 6;
volatile int e = c+d;
volatile int* f = (int*)&a;
volatile int g = *f;
std::cout << e << std::endl;
std::cout << g << std::endl;
return 0;
}
37 const int a = 2;
0x400955 <+0x0015> movl $0x2,(%rsp)
38 const int b = 3;
39 const int c = a+b;
40
41 volatile int d = 6;
0x400949 <+0x0009> movl $0x6,0x4(%rsp)
42 volatile int e = c+d;
0x400951 <+0x0011> mov 0x4(%rsp),%eax
0x40095c <+0x001c> add $0x5,%eax
0x40095f <+0x001f> mov %eax,0x8(%rsp)
43 volatile int* f = (int*)&a;
44 volatile int g = *f;
0x400963 <+0x0023> mov (%rsp),%eax
0x400966 <+0x0026> mov %eax,0xc(%rsp)
45
46 std::cout << e << std::endl;
0x400944 <+0x0004> mov $0x601060,%edi
0x40096a <+0x002a> mov 0x8(%rsp),%esi
0x40096e <+0x002e> callq 0x4008d0 <_ZNSolsEi#plt>
47 std::cout << g << std::endl;
0x40097b <+0x003b> mov 0xc(%rsp),%esi
0x40097f <+0x003f> mov $0x601060,%edi
0x400984 <+0x0044> callq 0x4008d0 <_ZNSolsEi#plt>
48 return 0;
So we can see that a is initialized into actual memory space, on the stack (I can tell cuz the rsp). But wait...c is dependent on a, but whenever I use c it is still a literal 5! What is happening here? Well, the compiler knows that a needs to be in a memory location because of the way it is used. However, it knows that the variable's value is never NOT 2, so whenever I use it in ways that don't need the memory, I can use it as a literal 2. Which means the a in line 37 is not the same as the a in line 43.
So where are const variables stored? They are stored where they NEED to be stored. CRAZY.
(btw, these were all compiled with g++ -g -O2, different compilers/flags will optimize it differently, this mostly demonstrates what the compiler can do, the only guarantee is that your code will behave correctly.)
Here's an example of taking the address of a const int and demonstrating that (in gcc on my machine, at least) it's stored as a local (not global static) variable.
#include <iostream>
const int *func() {
const int five = 5;
const int *p = &(five);
std::cout << *p << '\n';
return p;
}
// function to overwrite stack values left by earlier function call
int func2(int n, int x) {
for (int i = 0; i < x; ++i)
n *= 2;
return n;
}
int main() {
const int *p = func();
std::cout << func2(2, 10) << '\n';
std::cout << *p << '\n';
return 0;
}
Example output:
5
2048
1