Operator Overloading behaves differently for classes and primtives - c++

The following code when compiled and run using g++ outputs 22.
#include <iostream>
int main(){
int a = 5;
int c = ++a + ++a + ++a;
std::cout << c << std::endl;
return 0;
}
Floats also evaluate to the same value.
Whereas the following integer wrapper class outputs 24
#include <iostream>
class Int{
public:
int data;
Int( int value ) : data(value){}
Int& operator++(){
++data;
return *this;
}
Int operator+( const Int& b ){
return Int( data + b.data );
}
};
int main(){
Int a = 5;
Int c = ++a + ++a + ++a;
std::cout << c.data << std::endl;
return 0;
}
I am unable to understand why is there a difference in the outputs.
The first thing that came to my mind was the order of evaluation but shouldn't it be same for ints as well a classes.
I also thought if my implementation was wrong but most text also mentions the same implementation for prefix increment operator.
Could someone explain me in detail whats going on here?
Apart from this when both codes are compiled using clang the first code outputs 21 while the second code outputs 22.
PS : I know i shouldn't be using such an expression but my question is why are classes behaving differently than primitive types. Shouldn't they both parse to the same syntax tree and get evaluated in the same order. Even though the behaviour is undefined but for the same compiler, shouldn't they both behave in a similar manner

Both int c = ++a + ++a + ++a; and Int c = ++a + ++a + ++a; result in undefined behavior.
You should avoid coding like that.
See https://en.cppreference.com/w/cpp/language/operator_incdec#Example,
and see the Undefined behaviour section of cppreference.com's Order of evaluation page:
Undefined behavior
If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.
i = ++i + 2; // undefined behavior until C++11
i = i++ + 2; // undefined behavior until C++17
f(i = -2, i = -2); // undefined behavior until C++17
f(++i, ++i); // undefined behavior until C++17, unspecified after C++17
i = ++i + i++; // undefined behavior
If a side effect on a scalar object is unsequenced relative to a value computation using the value of the same scalar object, the behavior is undefined.
cout << i << i++; // undefined behavior until C++17
a[i] = i++; // undefined behavior until C++17
n = ++i + i; // undefined behavior
Here you can run your code with different compilers
Evaluation order on Visual C++
Evaluation order on Zapcc and GCC
Spoiler: Visual C++ behaves in the same way for primitive types and classes
On rextester you can try also Clang and GCC, but I can't add these links below the others without the editor telling me that there is some non-formatted code (which there isn't)
Evaluation order on Clang
Evaluation order on GCC

Related

C++ object behavior cannot predict [duplicate]

Hi all I stumbled upon this piece of code today and I am confused as to what exactly happens and more particular in what order :
Code :
#include <iostream>
bool foo(double & m)
{
m = 1.0;
return true;
}
int main()
{
double test = 0.0;
std::cout << "Value of test is : \t" << test << "\tReturn value of function is : " << foo(test) << "\tValue of test : " << test << std::endl;
return 0;
}
The output is :
Value of test is : 1 Return value of function is : 1 Value of test : 0
Seeing this I would assume that somehow the right most argument is printed before the call to the function. So this is right to left evaluation?? During debugging though it seems that the function is called prior to the output which is what I would expect. I am using Win7 and MSVS 2010. Any help is appreciated!
The evaluation order of elements in an expression is unspecified (except some very particular cases, such as the && and || operators and the ternary operator, which introduce sequence points); so, it's not guaranteed that test will be evaluated before or after foo(test) (which modifies it).
If your code relies on a particular order of evaluation the simplest method to obtain it is to split your expression in several separated statements.
The answer to this question changed in C++17.
Evaluation of overloaded operators are now sequenced in the same way as for built-in operators (C++17 [over.match.oper]/2).
Furthermore, the <<, >> and subscripting operators now have the left operand sequenced before the right, and the postfix-expression of a function call is sequenced before evaluation of the arguments.
(The other binary operators retain their previous sequencing, e.g. + is still unsequenced).
So the code in the question must now output Value of test is : 0 Return value of function is : 1 Value of test : 1. But the advice "Don't do this" is still reasonable, given that it will take some time for everybody to update to C++17.
Order of evaluation is unspecified. It is not left-to-right, right-to-left, or anything else.
Don't do this.
The order of evaluation is unspecified, see http://en.wikipedia.org/wiki/Sequence_point
This is the same situation as the example with the operator+ example:
Consider two functions f() and g(). In C and C++, the + operator is not associated with a sequence point, and therefore in the expression f()+g() it is possible that either f() or g() will be executed first.
the c++ reference explains very well why that should never be done (is causing an UB or undefined behaviour)
https://en.cppreference.com/w/cpp/language/operator_incdec
#include <iostream>
int main()
{
int n1 = 1;
int n2 = ++n1;
int n3 = ++ ++n1;
int n4 = n1++;
// int n5 = n1++ ++; // error
// int n6 = n1 + ++n1; // undefined behavior
std::cout << "n1 = " << n1 << '\n'
<< "n2 = " << n2 << '\n'
<< "n3 = " << n3 << '\n'
<< "n4 = " << n4 << '\n';
}
Notes
Because of the side-effects involved, built-in increment and decrement
operators must be used with care to avoid undefined behavior due to
violations of sequencing rules.
and in the section related to sequencing rules you can read the following:
Undefined behavior:
1) If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.
i = ++i + 2; // undefined behavior until C++11
i = i++ + 2; // undefined behavior until C++17
f(i = -2, i = -2); // undefined behavior until C++17
f(++i, ++i); // undefined behavior until C++17, unspecified after C++17
i = ++i + i++; // undefined behavior
2) If a side effect on a scalar object is unsequenced relative to a value computation using the value of the same scalar object, the behavior is undefined.
cout << i << i++; // undefined behavior until C++17
a[i] = i++; // undefined behavior until C++17
n = ++i + i; // undefined behavior

The time() function runs slow in Microsoft C++ [duplicate]

Hi all I stumbled upon this piece of code today and I am confused as to what exactly happens and more particular in what order :
Code :
#include <iostream>
bool foo(double & m)
{
m = 1.0;
return true;
}
int main()
{
double test = 0.0;
std::cout << "Value of test is : \t" << test << "\tReturn value of function is : " << foo(test) << "\tValue of test : " << test << std::endl;
return 0;
}
The output is :
Value of test is : 1 Return value of function is : 1 Value of test : 0
Seeing this I would assume that somehow the right most argument is printed before the call to the function. So this is right to left evaluation?? During debugging though it seems that the function is called prior to the output which is what I would expect. I am using Win7 and MSVS 2010. Any help is appreciated!
The evaluation order of elements in an expression is unspecified (except some very particular cases, such as the && and || operators and the ternary operator, which introduce sequence points); so, it's not guaranteed that test will be evaluated before or after foo(test) (which modifies it).
If your code relies on a particular order of evaluation the simplest method to obtain it is to split your expression in several separated statements.
The answer to this question changed in C++17.
Evaluation of overloaded operators are now sequenced in the same way as for built-in operators (C++17 [over.match.oper]/2).
Furthermore, the <<, >> and subscripting operators now have the left operand sequenced before the right, and the postfix-expression of a function call is sequenced before evaluation of the arguments.
(The other binary operators retain their previous sequencing, e.g. + is still unsequenced).
So the code in the question must now output Value of test is : 0 Return value of function is : 1 Value of test : 1. But the advice "Don't do this" is still reasonable, given that it will take some time for everybody to update to C++17.
Order of evaluation is unspecified. It is not left-to-right, right-to-left, or anything else.
Don't do this.
The order of evaluation is unspecified, see http://en.wikipedia.org/wiki/Sequence_point
This is the same situation as the example with the operator+ example:
Consider two functions f() and g(). In C and C++, the + operator is not associated with a sequence point, and therefore in the expression f()+g() it is possible that either f() or g() will be executed first.
the c++ reference explains very well why that should never be done (is causing an UB or undefined behaviour)
https://en.cppreference.com/w/cpp/language/operator_incdec
#include <iostream>
int main()
{
int n1 = 1;
int n2 = ++n1;
int n3 = ++ ++n1;
int n4 = n1++;
// int n5 = n1++ ++; // error
// int n6 = n1 + ++n1; // undefined behavior
std::cout << "n1 = " << n1 << '\n'
<< "n2 = " << n2 << '\n'
<< "n3 = " << n3 << '\n'
<< "n4 = " << n4 << '\n';
}
Notes
Because of the side-effects involved, built-in increment and decrement
operators must be used with care to avoid undefined behavior due to
violations of sequencing rules.
and in the section related to sequencing rules you can read the following:
Undefined behavior:
1) If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.
i = ++i + 2; // undefined behavior until C++11
i = i++ + 2; // undefined behavior until C++17
f(i = -2, i = -2); // undefined behavior until C++17
f(++i, ++i); // undefined behavior until C++17, unspecified after C++17
i = ++i + i++; // undefined behavior
2) If a side effect on a scalar object is unsequenced relative to a value computation using the value of the same scalar object, the behavior is undefined.
cout << i << i++; // undefined behavior until C++17
a[i] = i++; // undefined behavior until C++17
n = ++i + i; // undefined behavior

Why std::cout prints old value? [duplicate]

Hi all I stumbled upon this piece of code today and I am confused as to what exactly happens and more particular in what order :
Code :
#include <iostream>
bool foo(double & m)
{
m = 1.0;
return true;
}
int main()
{
double test = 0.0;
std::cout << "Value of test is : \t" << test << "\tReturn value of function is : " << foo(test) << "\tValue of test : " << test << std::endl;
return 0;
}
The output is :
Value of test is : 1 Return value of function is : 1 Value of test : 0
Seeing this I would assume that somehow the right most argument is printed before the call to the function. So this is right to left evaluation?? During debugging though it seems that the function is called prior to the output which is what I would expect. I am using Win7 and MSVS 2010. Any help is appreciated!
The evaluation order of elements in an expression is unspecified (except some very particular cases, such as the && and || operators and the ternary operator, which introduce sequence points); so, it's not guaranteed that test will be evaluated before or after foo(test) (which modifies it).
If your code relies on a particular order of evaluation the simplest method to obtain it is to split your expression in several separated statements.
The answer to this question changed in C++17.
Evaluation of overloaded operators are now sequenced in the same way as for built-in operators (C++17 [over.match.oper]/2).
Furthermore, the <<, >> and subscripting operators now have the left operand sequenced before the right, and the postfix-expression of a function call is sequenced before evaluation of the arguments.
(The other binary operators retain their previous sequencing, e.g. + is still unsequenced).
So the code in the question must now output Value of test is : 0 Return value of function is : 1 Value of test : 1. But the advice "Don't do this" is still reasonable, given that it will take some time for everybody to update to C++17.
Order of evaluation is unspecified. It is not left-to-right, right-to-left, or anything else.
Don't do this.
The order of evaluation is unspecified, see http://en.wikipedia.org/wiki/Sequence_point
This is the same situation as the example with the operator+ example:
Consider two functions f() and g(). In C and C++, the + operator is not associated with a sequence point, and therefore in the expression f()+g() it is possible that either f() or g() will be executed first.
the c++ reference explains very well why that should never be done (is causing an UB or undefined behaviour)
https://en.cppreference.com/w/cpp/language/operator_incdec
#include <iostream>
int main()
{
int n1 = 1;
int n2 = ++n1;
int n3 = ++ ++n1;
int n4 = n1++;
// int n5 = n1++ ++; // error
// int n6 = n1 + ++n1; // undefined behavior
std::cout << "n1 = " << n1 << '\n'
<< "n2 = " << n2 << '\n'
<< "n3 = " << n3 << '\n'
<< "n4 = " << n4 << '\n';
}
Notes
Because of the side-effects involved, built-in increment and decrement
operators must be used with care to avoid undefined behavior due to
violations of sequencing rules.
and in the section related to sequencing rules you can read the following:
Undefined behavior:
1) If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.
i = ++i + 2; // undefined behavior until C++11
i = i++ + 2; // undefined behavior until C++17
f(i = -2, i = -2); // undefined behavior until C++17
f(++i, ++i); // undefined behavior until C++17, unspecified after C++17
i = ++i + i++; // undefined behavior
2) If a side effect on a scalar object is unsequenced relative to a value computation using the value of the same scalar object, the behavior is undefined.
cout << i << i++; // undefined behavior until C++17
a[i] = i++; // undefined behavior until C++17
n = ++i + i; // undefined behavior

Why changed value does not take effect on a pass-by-reference variable during executing insertion operator chain [duplicate]

Hi all I stumbled upon this piece of code today and I am confused as to what exactly happens and more particular in what order :
Code :
#include <iostream>
bool foo(double & m)
{
m = 1.0;
return true;
}
int main()
{
double test = 0.0;
std::cout << "Value of test is : \t" << test << "\tReturn value of function is : " << foo(test) << "\tValue of test : " << test << std::endl;
return 0;
}
The output is :
Value of test is : 1 Return value of function is : 1 Value of test : 0
Seeing this I would assume that somehow the right most argument is printed before the call to the function. So this is right to left evaluation?? During debugging though it seems that the function is called prior to the output which is what I would expect. I am using Win7 and MSVS 2010. Any help is appreciated!
The evaluation order of elements in an expression is unspecified (except some very particular cases, such as the && and || operators and the ternary operator, which introduce sequence points); so, it's not guaranteed that test will be evaluated before or after foo(test) (which modifies it).
If your code relies on a particular order of evaluation the simplest method to obtain it is to split your expression in several separated statements.
The answer to this question changed in C++17.
Evaluation of overloaded operators are now sequenced in the same way as for built-in operators (C++17 [over.match.oper]/2).
Furthermore, the <<, >> and subscripting operators now have the left operand sequenced before the right, and the postfix-expression of a function call is sequenced before evaluation of the arguments.
(The other binary operators retain their previous sequencing, e.g. + is still unsequenced).
So the code in the question must now output Value of test is : 0 Return value of function is : 1 Value of test : 1. But the advice "Don't do this" is still reasonable, given that it will take some time for everybody to update to C++17.
Order of evaluation is unspecified. It is not left-to-right, right-to-left, or anything else.
Don't do this.
The order of evaluation is unspecified, see http://en.wikipedia.org/wiki/Sequence_point
This is the same situation as the example with the operator+ example:
Consider two functions f() and g(). In C and C++, the + operator is not associated with a sequence point, and therefore in the expression f()+g() it is possible that either f() or g() will be executed first.
the c++ reference explains very well why that should never be done (is causing an UB or undefined behaviour)
https://en.cppreference.com/w/cpp/language/operator_incdec
#include <iostream>
int main()
{
int n1 = 1;
int n2 = ++n1;
int n3 = ++ ++n1;
int n4 = n1++;
// int n5 = n1++ ++; // error
// int n6 = n1 + ++n1; // undefined behavior
std::cout << "n1 = " << n1 << '\n'
<< "n2 = " << n2 << '\n'
<< "n3 = " << n3 << '\n'
<< "n4 = " << n4 << '\n';
}
Notes
Because of the side-effects involved, built-in increment and decrement
operators must be used with care to avoid undefined behavior due to
violations of sequencing rules.
and in the section related to sequencing rules you can read the following:
Undefined behavior:
1) If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.
i = ++i + 2; // undefined behavior until C++11
i = i++ + 2; // undefined behavior until C++17
f(i = -2, i = -2); // undefined behavior until C++17
f(++i, ++i); // undefined behavior until C++17, unspecified after C++17
i = ++i + i++; // undefined behavior
2) If a side effect on a scalar object is unsequenced relative to a value computation using the value of the same scalar object, the behavior is undefined.
cout << i << i++; // undefined behavior until C++17
a[i] = i++; // undefined behavior until C++17
n = ++i + i; // undefined behavior

Static variable in C++ value is not getting updated even when incrementing in function [duplicate]

Hi all I stumbled upon this piece of code today and I am confused as to what exactly happens and more particular in what order :
Code :
#include <iostream>
bool foo(double & m)
{
m = 1.0;
return true;
}
int main()
{
double test = 0.0;
std::cout << "Value of test is : \t" << test << "\tReturn value of function is : " << foo(test) << "\tValue of test : " << test << std::endl;
return 0;
}
The output is :
Value of test is : 1 Return value of function is : 1 Value of test : 0
Seeing this I would assume that somehow the right most argument is printed before the call to the function. So this is right to left evaluation?? During debugging though it seems that the function is called prior to the output which is what I would expect. I am using Win7 and MSVS 2010. Any help is appreciated!
The evaluation order of elements in an expression is unspecified (except some very particular cases, such as the && and || operators and the ternary operator, which introduce sequence points); so, it's not guaranteed that test will be evaluated before or after foo(test) (which modifies it).
If your code relies on a particular order of evaluation the simplest method to obtain it is to split your expression in several separated statements.
The answer to this question changed in C++17.
Evaluation of overloaded operators are now sequenced in the same way as for built-in operators (C++17 [over.match.oper]/2).
Furthermore, the <<, >> and subscripting operators now have the left operand sequenced before the right, and the postfix-expression of a function call is sequenced before evaluation of the arguments.
(The other binary operators retain their previous sequencing, e.g. + is still unsequenced).
So the code in the question must now output Value of test is : 0 Return value of function is : 1 Value of test : 1. But the advice "Don't do this" is still reasonable, given that it will take some time for everybody to update to C++17.
Order of evaluation is unspecified. It is not left-to-right, right-to-left, or anything else.
Don't do this.
The order of evaluation is unspecified, see http://en.wikipedia.org/wiki/Sequence_point
This is the same situation as the example with the operator+ example:
Consider two functions f() and g(). In C and C++, the + operator is not associated with a sequence point, and therefore in the expression f()+g() it is possible that either f() or g() will be executed first.
the c++ reference explains very well why that should never be done (is causing an UB or undefined behaviour)
https://en.cppreference.com/w/cpp/language/operator_incdec
#include <iostream>
int main()
{
int n1 = 1;
int n2 = ++n1;
int n3 = ++ ++n1;
int n4 = n1++;
// int n5 = n1++ ++; // error
// int n6 = n1 + ++n1; // undefined behavior
std::cout << "n1 = " << n1 << '\n'
<< "n2 = " << n2 << '\n'
<< "n3 = " << n3 << '\n'
<< "n4 = " << n4 << '\n';
}
Notes
Because of the side-effects involved, built-in increment and decrement
operators must be used with care to avoid undefined behavior due to
violations of sequencing rules.
and in the section related to sequencing rules you can read the following:
Undefined behavior:
1) If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.
i = ++i + 2; // undefined behavior until C++11
i = i++ + 2; // undefined behavior until C++17
f(i = -2, i = -2); // undefined behavior until C++17
f(++i, ++i); // undefined behavior until C++17, unspecified after C++17
i = ++i + i++; // undefined behavior
2) If a side effect on a scalar object is unsequenced relative to a value computation using the value of the same scalar object, the behavior is undefined.
cout << i << i++; // undefined behavior until C++17
a[i] = i++; // undefined behavior until C++17
n = ++i + i; // undefined behavior