吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4164|回复: 16
收起左侧

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

[复制链接]
pk8900 发表于 2017-10-9 14:44
本帖最后由 pk8900 于 2017-10-9 18:36 编辑

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

[C++] 纯文本查看 复制代码
#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;    //结果正确:  21  31

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 编辑

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

附上修改后源码:最初的错误地方就是加引用和不加引用。
[C++] 纯文本查看 复制代码
#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;    //结果正确:  21  31

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默认不开优化的,当然炸了。
你自己看看开优化后的代码就知道为什么了
[C] 纯文本查看 复制代码
#include <stdio.h>


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

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




[Asm] 纯文本查看 复制代码
01361040 >/$  55            push ebp
01361041  |.  8BEC          mov ebp,esp
01361043  |.  83EC 20       sub esp,0x20
01361046  |.  A1 18303601   mov eax,dword ptr ds:[0x1363018]
0136104B  |.  0F57C0        xorps xmm0,xmm0
0136104E  |.  8945 E0       mov [local.8],eax
01361051  |.  A0 1C303601   mov al,byte ptr ds:[0x136301C]
01361056  |.  8845 E4       mov byte ptr ss:[ebp-0x1C],al
01361059  |.  8D45 E0       lea eax,[local.8]
0136105C  |.  50            push eax
0136105D  |.  68 20303601   push test.01363020                       ;  ASCII "%s\n"
01361062  |.  0F1145 E5     movups dqword ptr ss:[ebp-0x1B],xmm0
01361066  |.  66:C745 FD 00>mov word ptr ss:[ebp-0x3],0x0
0136106C  |.  660fd645 f5   movq qword ptr ss:[ebp-0xb],xmm0
01361071  |.  C645 FF 00    mov byte ptr ss:[ebp-0x1],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

免费评分

参与人数 1热心值 +1 收起 理由
pk8900 + 1 【前置++重载,返回一个引用】【后置++重载,返回一个对象】是否?

查看全部评分

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输出的就是一个被析构的变量的值,所以就输出了乱七八糟的东西

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
pk8900 + 1 + 1 不错,加了析构函数后确实是这样流程。return后调用了析构。

查看全部评分

LeoSky 发表于 2017-10-9 15:39
楼上正解

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

点评

return ++(*this); cout<<c3++ 还是会出错。  发表于 2017-10-9 16:33
LeoSky 发表于 2017-10-9 16:08
给你解释下吧
重点要了解变量的生命周期,了解引用的概念。

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

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
pk8900 + 1 + 1 谢谢,之前没想到返回引用tmp会被析构问题,只认为连写输出直接把C3传入。

查看全部评分

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

点评

release模式下是正确的,Debug模式下不正常,看来是VS的问题  发表于 2017-10-9 17:23
 楼主| 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问题 你把你修改后的代码贴出来。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 04:53

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表