I'm learning C++ and I have this problem:
#include <iostream>
using namespace std;
class test
{
public:
test(){};
test(int i):var{i}{};
test& operator++(){++var; return this;}
test operator++(int dummy){test tmp =*this;var++;return tmp;}
friend ostream& operator<<(ostream&, const test&);
private:
int var;
};
ostream& operator<<(ostream& o, const test& obj)
{
o<<obj.var;
return o;
}
int main()
{
test obj{2};
cout << obj << endl;
obj++;
cout << obj << endl;
cout << obj <<' '<< ++obj<<endl;
return 0;
}
the output i expected was: 2 3 3 4
instead i have: 2 3 4 4
if i replace the last increment ++obj with obj++ the situation is even more weird: 2 3 4 3
it's like the stream is read in the opposite way, can you help me?
Let's examine how the line
cout << obj << ' ' << ++obj << endl;
is translated.
Step 1.
cout << obj
becomes
// A non-member function.
operator<<(cout, obj)
Step 2.
operator<<(cout, obj) << ' '
becomes
// Also a non-member function.
operator<<(operator<<(cout, obj), ' ')
Step 3.
operator<<(operator<<(cout, obj), ' ') << ++obj
becomes
// Also a non-member function.
operator<<(operator<<(operator<<(cout, obj), ' '), ++obj)
Step 4.
operator<<(operator<<(operator<<(cout, obj), ' '), ++obj) << endl;
becomes
// A member function.
operator<<(operator<<(operator<<(cout, obj), ' '), ++obj).operator<<(endl);
That's the entire line.
In such an expression there is no guarantee that operator<<(cout, obj)
will be executed before ++obj
. It appears that in your platform, ++obj
is executed before operator<<(cout, obj)
is executed. That explains the behavior.
Please note that the standard has changed. If you are able to use C++17, you will get the expected behavior.
For starters the data member i can be uninitialized if the default constructor will be used.
Either declare the data member like
int var = 0;
Or redefine the default constructor for example by using the delegating constructor.
class test
{
public:
test() : test( 0 ){};
test(int i):var{i}{};
// ...
The pre-increment operator should look like
test& operator++(){++var; return *this;}
^^^^^
In the post-increment operator the identifier dummy
is not used. So remove it
test operator++( int ){test tmp =*this;var++;return tmp;}
This statement
cout << obj <<' '<< ++obj<<endl;
has undefined behavior because reading writing the object obj
are not sequenced.
You have to split this statement into two statements
cout << obj <<' ';
cout << ++obj<<endl;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.