Answer the question
In order to leave comments, you need to log in
In different IDEs, the code gives a different answer, how so?
#include <iostream>
#include <string>
using namespace std;
class A
{
int *val;
public:
A(){val = new int; *val = 0;}
int get(){return ++(*val);}
};
int main()
{
A a, b = a;
cout << a.get() << b.get();
return 0;
}
Answer the question
In order to leave comments, you need to log in
This is the case when seemingly simple code makes you understand the many intricacies of the language.
To better understand the processes taking place in the code, you first need to carefully look at the language standard.
What does the standard tell us about operator overloading ?
A declaration whose declarator-id is an operator-function-id shall declare a function or function template or an explicit instantiation or specialization of a function template. A function so declared is an operator function.
cout << a.get() << b.get();
std::ostream& operator << ( std::ostream&, int )
. operator << ()
the standard says that it is an overload in the form of an external function. operator<<( operator<<( cout, a.get() ), b.get() );
The evaluations of the postfix expression and of the arguments are all unsequenced relative to one another. All side effects of argument evaluations are sequenced before the function is entered (see 1.9).
if an operator function is invoked using operator notation, argument evaluation is sequenced as specified for the built-in operator; see 16.3.1.2.
cout << a.get() << b.get();
it can be simplified to cout << ++i << ++i;
, which should more clearly show the presence of UB. 2) The value computations (but not the side-effects) of the operands to any operator are sequenced before the value computation of the result of the operator (but not its side-effects).
3) When calling a function (whether or not the function is inline, and whether or not explicit function call syntax is used), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function.
5) The side effect of the built-in pre-increment and pre-decrement operators is sequenced before its value computation (implicit rule due to definition as compound assignment)
16) Every overloaded operator obeys the sequencing rules of the built-in operator it overloads when called using operator notation. (Since C++17)
19) In a shift operator expressionE1<<E2
andE1>>E2
, every value computation and side-effect of E1 is sequenced before every value computation and side effect of E2. (Since C++17)
cout << a.get() << b.get();
are evaluated is not defined, but the behavior of this code is defined. Therefore, when translated according to the C++14 standard, this code can produce either 12
, or 21
. But no 11
. cout << a.get() << b.get();
always unambiguous. When translating this code according to the C++17 standard (and beyond), the output to the console will always and only be 12
. cout << a.get() << b.get();
is undefined.Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question