By compiling this:
#include <iostream>
#include <sstream>
std::string makeList (std::string sep)
{
auto makeItem = [&] (std::string item)
{
static char count = '0';
return (++count, count) + sep + item + '\n';
};
return makeItem ("first") + makeItem ("second") + makeItem ("third");
}
int main()
{
std::cout << makeList (". ");
}
with gcc (5.4.0, c++11 flag) the output is this:
3. first
2. second
1. third
while the correct output, which clang (3.8, c++11 flag) gets, is:
1. first
2. second
3. third
Is there a particular reason for this behaviour?
According to cppreference:
Order of evaluation of the operands of almost all C++ operators (including the order of evaluation of function arguments in a function-call expression and the order of evaluation of the subexpressions within any expression) is unspecified. The compiler can evaluate operands in any order, and may choose another order when the same expression is evaluated again.
There is no right or wrong here, GCC evaluates right-to-left and clang left-to-right
Related
for the expression
(func1() * func2()) + func3()
will func1() * func2() be evaluated first as it has brackets or can the functions be called in any order like
first func3() and then (func1() * func2())
The functions can be called in any order.
Precedence of operators has got nothing to do anything with the order of evaluation of operands.
The C or C++ Standard doesn't determine the order in which the functions would be called. .
The order of evaluation of subexpressions, including
the arguments of a function call and
operands of operators (e.g., +, -, =, * , /), with the exception of:
the binary logical operators (&& and ||),
the ternary conditional operator (?:), and
the comma operator (,)
is Unspecified
For example
int Hello()
{
return printf("Hello"); /* printf() returns the number of
characters successfully printed by it
*/
}
int World()
{
return printf("World !");
}
int main()
{
int a = Hello() + World(); //might print Hello World! or World! Hello
/** ^
|
Functions can be called in either order
**/
return 0;
}
You can't make any assumptions about the order in which these functions will be called. It's perfectly valid for the compiler to call these functions in any order, assign the results to temporaries, and then use these temporary values to calculate the result of the expression.
These calls can be made in any order. You want to learn about C++ sequence points C++ sequence points.
Parenthesis in C/C++ force order of operations. func1() * func2() will be added to func3(), but the compiler can choose to call the functions in whatever order it wishes before passing in the results to the multiplication / addition operation.
It's natural to think that A+B is evaluated before C in this psudocode:
(A+b)*C
But in fact this is not so. The Standard says that the order of evaluation for all expressions is "Unspecified", unless otherwise specified by the Standard:
5/4 [expr]:
Except where noted, the order of
evaluation of operands of individual
operators and subexpressions of
individual expressions, and the order
in which side effects take place, is
unspecified
The Standard then goes on to identify a parenthesized expression as a "Primary expression" but does not specify the order of evaluation for Primary expressions. (5.1/5).
In Standardese, "Unspecified" does not mean "Undefined." Rather it means "Implementation Defined, but no documentation is required." So you might not even be able to say what the order of evaluation is for a specific compiler.
Here is a simple program illustrating the behavior:
#include <iostream>
#include <string>
using namespace std;
class Foo
{
public:
Foo(const string& name) : name_(name) {++i_; cout << "'" << name << "'(" << i_ << ")\n"; };
operator unsigned() const { return i_; }
Foo operator+(const Foo& rhs) const { string new_name = name_; new_name += "+"; new_name += rhs.name_; return Foo(new_name); }
private:
string name_;
static unsigned i_;
};
unsigned Foo::i_ = 0;
int main()
{
(Foo("A") + Foo("B")) + Foo("C");
}
On my MSVC10 running in Debug/x64 on Win7, the output happened to be:
'C'(1)
'B'(2)
'A'(3)
'A+B'(4)
'A+B+C'(5)
Apologies in advance, I know the general topic of evaluation order has had a lot of SO questions on it already. However, having looked at them, I want to clarify a few specific points that I don't think amount to a duplication of anything. Suppose I have the following code:
#include <iostream>
auto myLambda(int& n)
{
++n;
return [](int param) { std::cout << "param: " << param << std::endl; };
}
int main()
{
int n{0};
myLambda(n)(n);
return 0;
}
The program above outputs "n: 0" when I compile it. Here we have unspecified ordering at play: it could have just as easily output "n: 1" had a different evaluation order taken place.
My questions are:
What exactly is the sequencing relationship at play during the final function invocation above (i.e. the lambda-expression invocation), between the postfix expression myLambda(0), its argument n, and the subsequent function call itself?
Is the above an example of undefined or unspecified behaviour - and why exactly (with reference to the standard)?
If I changed the lambda code to [](int param) { std::cout << "hello" << std::endl } (i.e. made the outcome independent of its parameter and thus any evaluation order decisions, making behaviour deterministic) would the answer to 2) above still be the same?
EDIT: I've change the lambda parameter name from 'n' to 'param' because that seemed to be causing confusion.
Ironically (since the example uses C++11 features, and other answers have been distracted by that) the logic that makes this sample have unspecified behaviour dates back to C++98, Section 5, para 4
Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified. Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined.
Essentially the same clause exists in all C++ standards although, as noted in comment by Marc van Leeuwen, recent C++ standards no longer use the concept of sequence points. The net effect is the same: within a statement, the order or evaluation of operands of operators and subexpressions of individual expressions remains unspecified.
The unspecified behaviour occurs because an expression n is evaluated twice in the statement
myLambda(n)(n);
One evaluation of the expression n (to obtain a reference) is associated with the first (n) and another evaluation of an expression n (to obtain a value) is associated with the second (n). The order of evaluation of those two expressions (even though they are, optically, both n) is unspecified.
Similar clauses exist in ALL C++ standards, and have the same result - unspecified behaviour on the statement myLambda(n)(n), regardless of how myLambda() implemented
For example, myLambda() could be implemented in C++98 (and all later C++ standards, including C++11 and later) like this
class functor
{
functor() {};
int operator()(int n) { std::cout << "n: " << n << std::endl; };
};
functor myLambda(int &n)
{
++n;
return functor();
}
int main()
{
int n = 0;
myLambda(n)(n);
return 0;
}
since the code in the question is just a (C++11) technique (or shorthand) for achieving the same effect as this.
The above answers OP's questions 1. and 2. The unspecified behaviour occurs in main(), is unrelated to how myLambda() itself is implemented.
To answer the OP's third question, the behaviour is still unspecified if the lambda (or the functor's operator()) in my example) is modified to not access the value of its argument. The only difference is that the program as a whole produces no visible output that might vary between compilers.
The n in the definition of the lambda is a formal argument to the function that the lambda defines. It has no connection to the argument to myLambda that's also named n. The behavior here is dictated entirely by the way these two functions are called. In myLambda(n)(n) the order of evaluation of the two function arguments is unspecified. The lambda can be called with an argument of 0 or 1, depending in the compiler.
If the lambda had been defined with [=n]()... it would behave differently.
I didn't manage to find proper reference to standard but I see that it has similar behavior to argument evaluation order asked here and the order of function arguments evaluation is not defined by the standard:
5.2.2 Function call
8 [ Note: The evaluations of the postfix expression and of the argument expressions are all unsequenced relative to one another. All side effects of argument expression evaluations are sequenced before the function
is entered (see 1.9). —end note ]
So here's how it goes inside the calls on different compilers:
#include <iostream>
#include <functional>
struct Int
{
Int() { std::cout << "Int(): " << v << std::endl; }
Int(const Int& o) { v = o.v; std::cout << "Int(const Int&): " << v << std::endl; }
Int(int o) { v = o; std::cout << "Int(int): " << v << std::endl; }
~Int() { std::cout << "~Int(): " << v << std::endl; }
Int& operator=(const Int& o) { v = o.v; std::cout << "operator= " << v << std::endl; return *this; }
int v;
};
namespace std
{
template<>
Int&& forward<Int>(Int& a) noexcept
{
std::cout << "Int&: " << a.v << std::endl;
return static_cast<Int&&>(a);
}
template<>
Int&& forward<Int>(Int&& a) noexcept
{
std::cout << "Int&&: " << a.v << std::endl;
return static_cast<Int&&>(a);
}
}
std::function<void(Int)> myLambda(Int& n)
{
std::cout << "++n: " << n.v << std::endl;
++n.v;
return [&](Int m) {
std::cout << "n: " << m.v << std::endl;
};
}
int main()
{
Int n(0);
myLambda(n)(n);
return 0;
}
GCC g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out and MSVC
Int(int): 0
Int(const Int&): 0
++n: 0
Int&: 0
Int&: 0
Int(const Int&): 0
n: 0
~Int(): 0
~Int(): 0
~Int(): 1
So it creates variable and copies it to pass to returned lamba.
Clang clang++ -std=c++14 main.cpp && ./a.out
Int(int): 0
++n: 0
Int(const Int&): 1
Int&: 1
Int&: 1
Int(const Int&): 1
n: 1
~Int(): 1
~Int(): 1
~Int(): 1
Here it creates variable evaluates function and then passees copy the lamba.
And the order of evaluation is:
struct A
{
A(int) { std::cout << "1" << std::endl; }
~A() { std::cout << "-1" << std::endl; }
};
struct B
{
B(double) { std::cout << "2" << std::endl; }
~B() { std::cout << "-2" << std::endl; }
};
void f(A, B) { }
int main()
{
f(4, 5.);
}
MSVC and GCC:
2
1
-1
-2
Clang:
1
2
-2
-1
As in clang order is forward and the argument to lambda is passed after evaluation of the function's argument
Ṫhe behaviour is unspecified, because in the function call (myLambda(n))(n) the postfix expression (which I gave an extra redundant pair of parentheses) is unsequenced relative to the argument expression n (the rightmost one). However there is no undefined behaviour, because the modification of n takes place inside the function call myLambda(n). The only definite sequencing relation is that both evaluating myLambda(n) and the final n are obviously sequenced before the actual call of the lambda. For the final question, is the lambda chooses to completely ignore its argument, then the behaviour is no longer unspecified: though it is unspecified what value gets passed as parameter, there is no observable difference either way.
The order in which sub expressions are evaluated is unspecified and can vary apart from the operators &&, ||,? and ",".
The compiler knows both function prototyps myLambda and also the return lambda(extracted from the return type). Cause my first sentence the compiler is free which expression he evaluates first. Thats why you should never call to functions in on expression which have additional side effects.
I understand the problems with the classic example of
int i=0;
foo(i++, i++);
but I can't convince myself of whether the following is valid or invalid
int foo(int& i)
{
i=42;
return 99;
}
bar(foo(i), i);
I understand that the order 'foo(i)' and 'i' are evaluated is undefined, but what exactly does 'evaluated' mean? i.e. will the 2nd parameter of bar always be 42, or can the current value of 'i' be passed in before foo changes it?
No it is not guaranteed.
The order of evaluation of arguments to an function is Unspecified[Ref 1].
It can be possible that either:
foo(i) gets evaluated first or
i gets evaluated or
any other magical order(in case number of arguments were more than two)
Unspecified in this context means the implementation is allowed to implement the said feature whichever way they want and it need not be documented.
[Ref 1]
C++03 5.2.2 Function call
Para 8
The order of evaluation of arguments is unspecified. All side effects of argument expression evaluations take effect before the function is entered. The order of evaluation of the postfix expression and the argument expression list is unspecified.
This sample (gcc 4.6)
#include <iostream>
using namespace std;
int foo(int& i)
{
i=42;
return 99;
}
void bar(int i, int j)
{
cout << "i = " << i << "; j = " << j << endl;
}
int main()
{
int i =10;
bar(foo(i), i);
return 0;
}
gives i = 99, j = 10.
So it is really not guaranteed.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
cout << order of call to functions it prints?
What is the difference between order and associativity when evaluating a compound expression?
In the following example, I don't see the effect of order on the result of expression. The result is always 3 like the functions would have been called from left to right as arithmetic operators being left associative.
#include <iostream>
using std::cout;
using std::endl;
int Func1(int &i)
{
return i;
}
int Func2(int &i)
{
return i++;
}
int main()
{
for (int index = 0; index < 999999999; index++)
{
int i = 0;
int result = (Func2(i) + Func1(i) + Func1(i) + Func2(i));
cout << result << endl;
}
}
int result = (Func2(i) + Func1(i) + Func1(i) + Func2(i));
The order in which these functions are called is unspecified by the language!
The section $5/4 from the C++ Standard (2003) reads,
Except where noted, the order of
evaluation of operands of individual
operators and subexpressions of
individual expressions, and the order
in which side effects take place, is
unspecified.
So the free advice is : avoid writing such code. They're non-portable!
The result is very likely to be the same if you run the code multiple times, using the same compiler with the same compile options. However, if you change the options or try another compiler, you can get a different result.
As you use only simple functions on ints, there is nothing much to be gained from calling the functions in a different order, so either left-to-right or right-to-left would be the obvious choice. And your test code can't tell the difference! :-)
for the expression
(func1() * func2()) + func3()
will func1() * func2() be evaluated first as it has brackets or can the functions be called in any order like
first func3() and then (func1() * func2())
The functions can be called in any order.
Precedence of operators has got nothing to do anything with the order of evaluation of operands.
The C or C++ Standard doesn't determine the order in which the functions would be called. .
The order of evaluation of subexpressions, including
the arguments of a function call and
operands of operators (e.g., +, -, =, * , /), with the exception of:
the binary logical operators (&& and ||),
the ternary conditional operator (?:), and
the comma operator (,)
is Unspecified
For example
int Hello()
{
return printf("Hello"); /* printf() returns the number of
characters successfully printed by it
*/
}
int World()
{
return printf("World !");
}
int main()
{
int a = Hello() + World(); //might print Hello World! or World! Hello
/** ^
|
Functions can be called in either order
**/
return 0;
}
You can't make any assumptions about the order in which these functions will be called. It's perfectly valid for the compiler to call these functions in any order, assign the results to temporaries, and then use these temporary values to calculate the result of the expression.
These calls can be made in any order. You want to learn about C++ sequence points C++ sequence points.
Parenthesis in C/C++ force order of operations. func1() * func2() will be added to func3(), but the compiler can choose to call the functions in whatever order it wishes before passing in the results to the multiplication / addition operation.
It's natural to think that A+B is evaluated before C in this psudocode:
(A+b)*C
But in fact this is not so. The Standard says that the order of evaluation for all expressions is "Unspecified", unless otherwise specified by the Standard:
5/4 [expr]:
Except where noted, the order of
evaluation of operands of individual
operators and subexpressions of
individual expressions, and the order
in which side effects take place, is
unspecified
The Standard then goes on to identify a parenthesized expression as a "Primary expression" but does not specify the order of evaluation for Primary expressions. (5.1/5).
In Standardese, "Unspecified" does not mean "Undefined." Rather it means "Implementation Defined, but no documentation is required." So you might not even be able to say what the order of evaluation is for a specific compiler.
Here is a simple program illustrating the behavior:
#include <iostream>
#include <string>
using namespace std;
class Foo
{
public:
Foo(const string& name) : name_(name) {++i_; cout << "'" << name << "'(" << i_ << ")\n"; };
operator unsigned() const { return i_; }
Foo operator+(const Foo& rhs) const { string new_name = name_; new_name += "+"; new_name += rhs.name_; return Foo(new_name); }
private:
string name_;
static unsigned i_;
};
unsigned Foo::i_ = 0;
int main()
{
(Foo("A") + Foo("B")) + Foo("C");
}
On my MSVC10 running in Debug/x64 on Win7, the output happened to be:
'C'(1)
'B'(2)
'A'(3)
'A+B'(4)
'A+B+C'(5)