This question already has answers here:
Order of evaluation in C++ function parameters
(6 answers)
Warn about UB in argument evaluation order
(1 answer)
Closed 2 years ago.
I'm new at programming. This is part of my code:
double logic(double a,double b)
{
(Code Here...)
}
double inputDouble(double x)
{
std::cout << "Please, input a floating number: ";
std::cin >> x;
std::cout << std::endl;
return x;
}
int main()
{
double a,b;
std::cout << logic(inputDouble(a),inputDouble(b));
return 0;
}
I've noticed the problem on the compiler, them I've checked the debug windows and the problem that I'm having is that when I insert a value on 'a' by 'inputDouble' function, it goes to 'b', and vice-versa. So at the end of the program what I get in 'logic' function is: double a=b(From main()), double b=a(From main()). I hope and am grateful to someone who can explain to me what I'm doing wrong so the variables are being assigned on the wrong places. And I also apologize if there is any gramatical mistake on this post as english is not my first language.
The expression:
logic(inputDouble(a),inputDouble(b))
does not guarantee the order in which those calls to inputDouble() are made, just that they're both complete before the call to logic(). So it may call the a one first, or it may call the b one first(a).
To guarantee order, you can use something like:
double inputDouble() { // slight change, see below.
double x;
std::cout << "Please, input a floating number: ";
std::cin >> x;
std::cout << std::endl;
return x;
}
int main() {
double a = inputDouble(); // guarantee get 'a' first.
double b = inputDouble();
std::cout << logic(a, b);
return 0;
}
You could also use:
double a = inputDouble(); // guarantee get 'a' first.
std::cout << logic(a, inputDouble());
but I prefer the first one for consistency.
You'll notice a slight change to the inputDouble() function as well to remove the parameter, no useful purpose is served by passing the uninitialised values to the function, then over-writing and returning it.
Instead, I've just used a local variable to receive the value and return it.
A more robust program would also ensure that user input was valid but that can be left for a different question, since it almost certainly already exists on this site.
(a) For the language lawyers amongst us, this is covered in C++20 [expr.call] /8 (my emphasis):
The initialization of a parameter, including every associated value computation and side effect, is indeterminately sequenced with respect to that of any other parameter. [Note: All side effects of argument evaluations are sequenced before the function is entered].
Related
int a = 1;
int &b = a;
Here, the reference b has a type int, but, what is the purpose of it having a type when it is not an object? What if that type was different of that of the object it refers to?
The purpose of having typed references (i.e. pointers) is to enable type checking (which helps to catch bugs). If you were to declare a reference as a different type, you will get a type error (you can cast it, but that needs to be done explicitly).
According to Sumita Arora's book 'Computer Science with C++' The reference variables are often treated as derived data type in which it has a property of storing variable addresses.It is means of providing an alias to the existing variable.That is existing variable can be called by using this alternate names.
Suppose when we want to perform swapping of two variables using references.
// function definition to swap the values.
void swap(int &x, int &y) {
int temp;
temp = x; // save the value at address x
x = y; // put y into x
y = temp; // put x into y
return;
}
void main () {
// local variable declaration:
int a = 100;
int b = 200;
cout << "Before swap, value of a :" << a << endl;
cout << "Before swap, value of b :" << b << endl;
/* calling a function to swap the values using variable reference.*/
swap(a, b);
cout << "After swap, value of a :" << a << endl;
cout << "After swap, value of b :" << b << endl;
getch();
}
Here,swapping is performed using call by reference method and the changes will be reflected at actual parameters also.Here modification of passed parameters are done quite easily which serves one of its actual purpose.Whenever,there is a comparison with integer variable and a reference variable during swapping,the possible error might occur is type mismatch error,since address is being compared with value.Here integer references are used to identify that it could store addresses of integer variables only, which is possibly a mechanism developed to tackle type mismatch errors and make compiler identify that the given address holds an integer or the datatype specified by reference such that the program runs smoothly and performs operations.References also eliminates wild pointer cases and often provides easy-to-use interface.
Here is my problem:
int addsomeStuff(std::ostream &cout, int b) {
cout << b;
return 2;
}
int main() {
int a = 1;
cout << a << addsomeStuff(cout, 3) << endl;
return 0;
}
Output: 312
Can Someone explain me the Output, i would expect the output more like 132
why is the compiler runs first the Function before making the operator.
How i run into this issue:
I have a container class which can hold data inside an bytearray.
Somehow the 'container.WriteConvert(..);' get inserted into bytearray before the integer called 'a'. Does anyone have an explaintation for that.
I could make the WriteConvert static or add an extra Line which would fix this problem, instead of returning an Container& but i am kinda intrested whats the reason the Compiler puts this in this order.
int a = 2;
Container container;
container << a << container.WriteConvert("TestString");
int b = 0;
container >> b;
cout << b;
// The ouput of 'b' is some stupid Data which is caused by WriteConvert.
The Reason i didnt wrote this WriteConvert static or outside of the Container class has some reason. I have also ReadConvert which i dont want to have multiline. If someone has another idea i am open for other solutions, without increasing line amount.
int b = 0;
string output
container >> b >> container.ReadConvert(output);
cout << b;
Pre C++17, the order of evaluation of the chained operator arguments' was unspecified. That means the execution could've first evaluated addsomeStuff(cout, 3) call (thus printing 3 first) and then proceed to print a and the returned value of addsomeStuff(cout, 3).
With C++17, the order of evaluation is well defined - left to right. That means that if your compiler correctly implements the C++17 standard, the only possible output is 132.
If you are stuck with a pre C++17 standard, you would need to first evaluate all the arguments and then use them in chained operator call or don't use chained operator calls:
int main() {
int a = 1;
cout << a;
cout << addsomeStuff(cout, 3) << endl;
return 0;
}
The former approach may alter the behaviour, but will be well-defined.
I have some doubts about C++ reference parameters. I am learning from this website:
http://www.doc.ic.ac.uk/~wjk/c++Intro/RobMillerL3.html
First program:
#include<iostream>
using namespace std;
int area(int length, int width);
int main()
{
int this_length, this_width;
cout << "Enter the length: ";
cin >> this_length;
cout << "Enter the width: ";
cin >> this_width;
cout << "\n";
cout << "The area of a " << this_length << "x" << this_width;
cout << " rectangle is " << area(this_length, this_width) << endl;
return 0;
}
int area(int length, int width)
{
int number;
number = length * width
return number;
}
Then the author suggests that "under some circumstances, it is legitimate to require a function to modify the value of an actual parameter that it is passed".After that he introduces new function:
void get_dimensions(int& length, int& width)
{
cout << "Enter the length: ";
cin >> length;
cout << "Enter the width: ";
cin >> width;
cout << "\n";
}
What is the main advantage when we pass values as parameters?
Advantages of passing by reference:
It allows us to have the function change the value of the argument, which is sometimes useful.
Because a copy of the argument is not made, it is fast, even when used with large structs or classes.
We can pass by const reference to avoid unintentional changes.
We can return multiple values from a function.
Disadvantages of passing by reference:
Because a non-const reference can not be made to a literal or an expression, reference arguments must be normal variables.
It can be hard to tell whether a parameter passed by reference is meant to be input, output, or both.
It’s impossible to tell from the function call that the argument may change. An argument passed by value and passed by reference looks the same. We can only tell whether an argument is passed by value or reference by looking at the function declaration. This can lead to situations where the programmer does not realize a function will change the value of the argument.
Because references are typically implemented by C++ using pointers, and dereferencing a pointer is slower than accessing it directly, accessing values passed by reference is slower than accessing values passed by value.
Sources:
http://www.learncpp.com/cpp-tutorial/73-passing-arguments-by-reference/
http://www.functionx.com/cppcli/functions/Lesson10b.htm
https://en.wikibooks.org/wiki/C++_Programming/Code/Statements/Functions
There is already a good answer (imho worth accepting). However, I would like to give a more basic answer, as it seems like you encountered passing by reference for the first time:
This function:
void foo(int x){x +=1;}
can do anything with the value of the passed (by value) parameter, but it has no chance to return anything to the caller, i.e. the x+=1 has practically no effect at all.
On the other hand, this function:
void bar(int& x){x +=1;}
gets not only the value, but it is working on the actual variable that you pass as parameter (by reference). Thus the x+=1 has an effect also outside of the function.
Both functions in action:
int main(){
int a = 1;
foo(a); // foo gets a copy of a and increments its value
// a is still 1
bar(a); // bar directly increments the value of a
// a is now 2
}
This is the main difference of passing a parameters by reference (bar) vs passing by value (foo). The main advantage of passing by reference is that the value of the parameter needs not to be copied. (This is whypassing by value is usually done with a const reference. Passing a const reference is like passing the value because the value cannot be changed even if actually a reference is passed.) However, for more details I refer to Rohits answer.
int &a is a reference to any parameter passed to that function, You should always think of references as Alias to a variable (it is similar to a const pointer).
If your reference is not const you are allowed to changed and therefore change the content of the original variable.
It is useful for many reason first of all it can improve performances by avoiding doing copies when passing a parameter by reference, and it is also useful if you have a function that your expecting to return multiple results for example =:
int f (int &a,int &b,int &c,int&d);
int main
{
int first,second,third,result;
result = f(first,third,result);
}
All your int variables can be change within you function.
I have done some experimentation on rvalue references with the TDM-GCC 4.6.1 compiler and made some interesting observations that I cannot explain away with theories. I would like experts out there to help me explain them.
I have a very simple program that does not deal with objects but int primitives and that has defined 2 functions:
foo1 (returning a local variable by rvalue reference) and
foo2 (returning a local variable by value)
#include <iostream>
using namespace std;
int &&foo1();
int foo2();
int main()
{
int&& variable1 = foo1();
//cout << "My name is softwarelover." << endl;
cout << "variable1 is: " << variable1 << endl; // Prints 5.
cout << "variable1 is: " << variable1 << endl; // Prints 0.
int&& variable2 = foo2();
cout << "variable2 is: " << variable2 << endl; // Prints 5.
cout << "variable2 is still: " << variable2 << endl; // Still prints 5!
return 0;
}
int &&foo1() {
int a = 5;
return static_cast<int&&>(a);
}
int foo2() {
int a = 5;
return a;
}
It seems the value returned by foo1 and received by variable1 dies out after some time - perhaps, a brief period of some milliseconds. Notice that I have prevented cout from printing "My name is softwarelover" by commenting it out. If I allow that statement to run, the result is different. Instead of printing 5, 0 it prints 0, 0. Seems like it is because of the time-delay introduced by "cout << "My name is softwarelover." that 5 turns into 0.
Is the above how an rvalue reference is supposed to behave when referring to a primitive integer which a function returned by reference as opposed to return-by-value? By the way, why is it 0, why not garbage?
Notice also that variable2 never seems to die out, no matter how many times I print it with cout! variable2 refers to a primitive integer which a function returned by value, not return-by-reference.
Thanks.
Rvalue references are still just references. A reference to a function local variable is invalid after the function returns. You're lucky your rvalue reference is 5 for any time at all after the function call, because it is technically invalid after the function returns.
Edit: I'm expanding upon my answer, hoping that some people will find some extra detail useful.
A variable defined inside a function is a function local variable. The lifetime of that variable is limited to inside the function that it was declared in. You can think of it as being 'destroyed' when the function returns, but it's not really destroyed. If it's an object, then its destructor will be called, but the memory that held the variable is still there. Any references or pointers you had to that variable still point to the same spot in memory, but that memory has been re-purposed (or may be re-purposed at some indeterminate time in the future).
The old values (in your case '5') will still be there for a while, until something comes along and overwrites it. There is no way to know how long the values will still be there, and no one should ever depend on them still being there for any amount of time after the function returns. Consider any references (or pointers) to function local variables invalid once the function returns. Metaphorically, if you go knocking on the door you probably won't find the new tenant agreeable.
I'm a TA for an intro C++ class. The following question was asked on a test last week:
What is the output from the following program:
int myFunc(int &x) {
int temp = x * x * x;
x += 1;
return temp;
}
int main() {
int x = 2;
cout << myFunc(x) << endl << myFunc(x) << endl << myFunc(x) << endl;
}
The answer, to me and all my colleagues, is obviously:
8
27
64
But now several students have pointed out that when they run this in certain environments they actually get the opposite:
64
27
8
When I run it in my linux environment using gcc I get what I would expect. Using MinGW on my Windows machine I get what they're talking about.
It seems to be evaluating the last call to myFunc first, then the second call and then the first, then once it has all the results it outputs them in the normal order, starting with the first. But because the calls were made out of order the numbers are opposite.
It seems to me to be a compiler optimization, choosing to evaluate the function calls in the opposite order, but I don't really know why. My question is: are my assumptions correct? Is that what's going on in the background? Or is there something totally different? Also, I don't really understand why there would be a benefit to evaluating the functions backwards and then evaluating output forward. Output would have to be forward because of the way ostream works, but it seems like evaluation of the functions should be forward as well.
Thanks for your help!
The C++ standard does not define what order the subexpressions of a full expression are evaluated, except for certain operators which introduce an order (the comma operator, ternary operator, short-circuiting logical operators), and the fact that the expressions which make up the arguments/operands of a function/operator are all evaluated before the function/operator itself.
GCC is not obliged to explain to you (or me) why it wants to order them as it does. It might be a performance optimisation, it might be because the compiler code came out a few lines shorter and simpler that way, it might be because one of the mingw coders personally hates you, and wants to ensure that if you make assumptions that aren't guaranteed by the standard, your code goes wrong. Welcome to the world of open standards :-)
Edit to add: litb makes a point below about (un)defined behavior. The standard says that if you modify a variable multiple times in an expression, and if there exists a valid order of evaluation for that expression, such that the variable is modified multiple times without a sequence point in between, then the expression has undefined behavior. That doesn't apply here, because the variable is modified in the call to the function, and there's a sequence point at the start of any function call (even if the compiler inlines it). However, if you'd manually inlined the code:
std::cout << pow(x++,3) << endl << pow(x++,3) << endl << pow(x++,3) << endl;
Then that would be undefined behavior. In this code, it is valid for the compiler to evaluate all three "x++" subexpressions, then the three calls to pow, then start on the various calls to operator<<. Because this order is valid and has no sequence points separating the modification of x, the results are completely undefined. In your code snippet, only the order of execution is unspecified.
Exactly why does this have unspecified behaviour.
When I first looked at this example I felt that the behaviour was well defined because this expression is actually short hand for a set of function calls.
Consider this more basic example:
cout << f1() << f2();
This is expanded to a sequence of function calls, where the kind of calls depend on the operators being members or non-members:
// Option 1: Both are members
cout.operator<<(f1 ()).operator<< (f2 ());
// Option 2: Both are non members
operator<< ( operator<<(cout, f1 ()), f2 () );
// Option 3: First is a member, second non-member
operator<< ( cout.operator<<(f1 ()), f2 () );
// Option 4: First is a non-member, second is a member
cout.operator<<(f1 ()).operator<< (f2 ());
At the lowest level these will generate almost identical code so I will refer only to the first option from now.
There is a guarantee in the standard that the compiler must evaluate the arguments to each function call before the body of the function is entered. In this case, cout.operator<<(f1()) must be evaluated before operator<<(f2()) is, since the result of cout.operator<<(f1()) is required to call the other operator.
The unspecified behaviour kicks in because although the calls to the operators must be ordered there is no such requirement on their arguments. Therefore, the resulting order can be one of:
f2()
f1()
cout.operator<<(f1())
cout.operator<<(f1()).operator<<(f2());
Or:
f1()
f2()
cout.operator<<(f1())
cout.operator<<(f1()).operator<<(f2());
Or finally:
f1()
cout.operator<<(f1())
f2()
cout.operator<<(f1()).operator<<(f2());
The order in which function call parameters is evaluated is unspecified. In short, you shouldn't use arguments that have side-effects that affect the meaning and result of the statement.
Yeah, the order of evaluation of functional arguments is "Unspecified" according to the Standards.
Hence the outputs differ on different platforms
As has already been stated, you've wandered into the haunted forest of undefined behavior. To get what is expected every time you can either remove the side effects:
int myFunc(int &x) {
int temp = x * x * x;
return temp;
}
int main() {
int x = 2;
cout << myFunc(x) << endl << myFunc(x+1) << endl << myFunc(x+2) << endl;
//Note that you can't use the increment operator (++) here. It has
//side-effects so it will have the same problem
}
or break the function calls up into separate statements:
int myFunc(int &x) {
int temp = x * x * x;
x += 1;
return temp;
}
int main() {
int x = 2;
cout << myFunc(x) << endl;
cout << myFunc(x) << endl;
cout << myFunc(x) << endl;
}
The second version is probably better for a test, since it forces them to consider the side effects.
And this is why, every time you write a function with a side-effect, God kills a kitten!