pk8900 发表于 2017-10-9 14:44

【已解决】C++一元运算符,左移运算符重载结果出错

本帖最后由 pk8900 于 2017-10-9 18:36 编辑

一元运算符,左移运算符重载,左移与后置++连写输出结算出错。

#include<iostream>
using namespace std;
class MyClass
{
public:
      friend ostream & operator<<(ostream &out,MyClass & C1);
      MyClass(int a=0,int b=0)
                {
                this->a=a;
                this->b=b;
                }
      void Print()
                {
                cout<<"a:"<<a<<"   b:"<<b<<endl;
                }
      MyClass operator++()
                {
                this->a++;
                this->b++;
                return*this;
                }
      MyClass& operator++(int)
                {
                MyClass tmp=*this;
                this->a++;
                this->b++;
                return tmp;
                }
protected:
private:
      int a,b;
};
ostream &operator<<(ostream &out,MyClass & C5)
      {
      out<<"输出MyClass类:";
      out<<C5.a<<""<<C5.b<<endl;
      return out;
      }
void main()
{

MyClass C3(20,30);
cout<<"++C3 结果:"<<endl;
cout<<++C3;    //结果正确:2131

cout<<"C3++:结果:"<<endl;
C3++;
cout<<C3;   //结果正确: 22 32

cout<<"C3++:结果:"<<endl;
cout<<C3++;   //结果错误: -XXXXXX-XXXXXX 这里为什么是未初始化数据
system("pause");
}


行:51    cout<<C3++;   这句代码输出的结果不是预想的: 23 33 或者 22 32,大家帮忙给看看,为什么会出错。

pk8900 发表于 2017-10-9 18:17

本帖最后由 pk8900 于 2017-10-9 18:27 编辑

【前置++重载,返回一个引用】【后置++重载,返回一个对象】

附上修改后源码:最初的错误地方就是加引用和不加引用。
#include<iostream>
using namespace std;
class MyClass
{
public:
      friend ostream & operator<<(ostream &out,MyClass & C1);
      MyClass(int a=0,int b=0)
                {
                this->a=a;
                this->b=b;
                }
      void Print()
                {
                cout<<"a:"<<a<<"   b:"<<b<<endl;
                }
      //前置++重载,返回一个引用
      MyClass& operator++()
                {
                this->a++;
                this->b++;
                return*this;
                }
      //后置++重载,返回一个对象
      MyClass operator++(int)
                {
                MyClass tmp=*this;
                this->a++;
                this->b++;
                return tmp;
                //return ++(*this);
                }
      ~MyClass()
                {
                cout<<"析构"<<endl;
                }
protected:
private:
      int a,b;
};
ostream &operator<<(ostream &out,MyClass & C5)
      {
      out<<"输出MyClass类:";
      out<<C5.a<<""<<C5.b<<endl;
      return out;
      }
void main()
{

MyClass C3(20,30);
cout<<"++C3 结果:"<<endl;
cout<<++C3;    //结果正确:2131

cout<<"C3++:结果:"<<endl;
C3++;
cout<<C3;   //结果正确: 22 32

cout<<"C3++:结果:"<<endl;
cout<<C3++;   //结果错误: -XXXXXX-XXXXXX   结果正确: 22 32

system("pause");
}

SeriousSnow 发表于 2017-10-9 17:47

pk8900 发表于 2017-10-9 17:21
release模式下是正确的,Debug模式下不正常,看来是VS的问题。

debug默认不开优化的,当然炸了。
你自己看看开优化后的代码就知道为什么了
#include <stdio.h>


char * f()
{
        char str = "haha";
        return str;
}

int main(int argc, char ** argv)
{
        printf("%s\n",f());
        return 0;
}




01361040 >/$55            push ebp
01361041|.8BEC          mov ebp,esp
01361043|.83EC 20       sub esp,0x20
01361046|.A1 18303601   mov eax,dword ptr ds:
0136104B|.0F57C0      xorps xmm0,xmm0
0136104E|.8945 E0       mov ,eax
01361051|.A0 1C303601   mov al,byte ptr ds:
01361056|.8845 E4       mov byte ptr ss:,al
01361059|.8D45 E0       lea eax,
0136105C|.50            push eax
0136105D|.68 20303601   push test.01363020                     ;ASCII "%s\n"
01361062|.0F1145 E5   movups dqword ptr ss:,xmm0
01361066|.66:C745 FD 00>mov word ptr ss:,0x0
0136106C|.660fd645 f5   movq qword ptr ss:,xmm0
01361071|.C645 FF 00    mov byte ptr ss:,0x0
01361075|.E8 96FFFFFF   call test.printfTStartupile_modenitializ>
0136107A|.83C4 08       add esp,0x8
0136107D|.33C0          xor eax,eax
0136107F|.8BE5          mov esp,ebp
01361081|.5D            pop ebp                                  ;kernel32.75BE8744

LeoSky 发表于 2017-10-9 15:22

        MyClass& operator++(int)
        {
                MyClass tmp = *this;
                this->a++;
                this->b++;
                return tmp;
        }

这里的问题,你仔细看下。

pk8900 发表于 2017-10-9 15:31

LeoSky 发表于 2017-10-9 15:22
MyClass& operator++(int)
        {
                MyClass tmp = *this;


MyClass& operator++(int)
      {
                MyClass tmp = *this;
                this->a++;
                this->b++;
                return tmp;//改为return *this的话和前置++就一样了,可以正常,但返回 tmp 就不行。
      }
这里返回值传到:
ostream &operator<<(ostream &out,MyClass & C5)
      {
      out<<"输出MyClass类:";
      out<<C5.a<<""<<C5.b<<endl;
      return out;
      }
C5即为未初始化的值了。

Aerse 发表于 2017-10-9 15:37

MyClass& operator++(int)
      {
                MyClass tmp = *this;
                this->a++;
                this->b++;
                return tmp;
      }

返回值是tmp的引用,tmp是临时变量,出了函数就被析构了,你外边cout输出的就是一个被析构的变量的值,所以就输出了乱七八糟的东西

LeoSky 发表于 2017-10-9 15:39

楼上正解

        MyClass& operator++()
        {
                this->a++;
                this->b++;
                return*this;
        }
        MyClass& operator++(int)
        {
                return ++(*this);
        }

LeoSky 发表于 2017-10-9 16:08

给你解释下吧
重点要了解变量的生命周期,了解引用的概念。

额外解释:
   此例中的 MyClass tmp = *this; 生命周期在这个函数的作用域内,数据存在栈上,且是通过二进制拷贝到tmp里(因为没有写重载=运算符)
在出了这个作用域以后其实数据并没有被重写或删除(因为没有写析构函数)此时里面的数据是 执行++ 前对象里面的数据,但这个数据不属于任何人,当前线程可以随时操作它,所有这个数据就是不安全的了。
接着调用<<运算符来输出的时候 在Debug模式下 会对进入函数时候申请的栈空间进行填充0xCC操作,就在此时,你上面的那个对象里面的数据就被覆盖成了0xCCCCCCCC,所有你再输出的时候以前那个tmp对象
的内存地址里面数据就是这个样子了。不知道你是否理解。

LeoSky 发表于 2017-10-9 16:53

还出错?你第一个++ 函数 返回的是临时变量,同样的问题,你可以按照我上面写的那样 ,返回引用。

pk8900 发表于 2017-10-9 17:19

LeoSky 发表于 2017-10-9 16:53
还出错?你第一个++ 函数 返回的是临时变量,同样的问题,你可以按照我上面写的那样 ,返回引用。

是的,我试了,这回不是两个负数,而是两个267455040

pk8900 发表于 2017-10-9 17:21

release模式下是正确的,Debug模式下不正常,看来是VS的问题。

LeoSky 发表于 2017-10-9 17:25

pk8900 发表于 2017-10-9 17:21
release模式下是正确的,Debug模式下不正常,看来是VS的问题。

不是VS问题 你把你修改后的代码贴出来。
页: [1] 2
查看完整版本: 【已解决】C++一元运算符,左移运算符重载结果出错