简体   繁体   English

链接operator <<和operator ++的问题

[英]Problem with chaining operator<< and operator++

I'm learning C++ and I have this problem: 我正在学习C ++,但遇到了以下问题:

#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 我期望的输出是:2 3 3 4

instead i have: 2 3 4 4 相反,我有:2 3 4 4

if i replace the last increment ++obj with obj++ the situation is even more weird: 2 3 4 3 如果我用obj ++替换最后一个增量++ obj,情况将更加奇怪: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. 第1步。

cout << obj

becomes 变成

// A non-member function.
operator<<(cout, obj)

Step 2. 第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 . 在这样的表达式中,不能保证operator<<(cout, obj)将在++obj之前执行。 It appears that in your platform, ++obj is executed before operator<<(cout, obj) is executed. 看来在您的平台上, ++obj是在执行operator<<(cout, obj)执行的。 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. 如果您能够使用C ++ 17,则将获得预期的行为。

For starters the data member i can be uninitialized if the default constructor will be used. 对于初学者,如果使用默认构造函数,则数据成员i可以未初始化。

Either declare the data member like 要么像这样声明数据成员

int var = 0; 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. 在后递增运算符中,不使用标识符dummy 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. 具有未定义的行为,因为读写对象obj时未排序。

You have to split this statement into two statements 您必须将此语句分为两个语句

cout << obj <<' ';
cout << ++obj<<endl;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM