【已解决】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: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");
}
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
MyClass& operator++(int)
{
MyClass tmp = *this;
this->a++;
this->b++;
return tmp;
}
这里的问题,你仔细看下。 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即为未初始化的值了。 MyClass& operator++(int)
{
MyClass tmp = *this;
this->a++;
this->b++;
return tmp;
}
返回值是tmp的引用,tmp是临时变量,出了函数就被析构了,你外边cout输出的就是一个被析构的变量的值,所以就输出了乱七八糟的东西 楼上正解
MyClass& operator++()
{
this->a++;
this->b++;
return*this;
}
MyClass& operator++(int)
{
return ++(*this);
}
给你解释下吧
重点要了解变量的生命周期,了解引用的概念。
额外解释:
此例中的 MyClass tmp = *this; 生命周期在这个函数的作用域内,数据存在栈上,且是通过二进制拷贝到tmp里(因为没有写重载=运算符)
在出了这个作用域以后其实数据并没有被重写或删除(因为没有写析构函数)此时里面的数据是 执行++ 前对象里面的数据,但这个数据不属于任何人,当前线程可以随时操作它,所有这个数据就是不安全的了。
接着调用<<运算符来输出的时候 在Debug模式下 会对进入函数时候申请的栈空间进行填充0xCC操作,就在此时,你上面的那个对象里面的数据就被覆盖成了0xCCCCCCCC,所有你再输出的时候以前那个tmp对象
的内存地址里面数据就是这个样子了。不知道你是否理解。 还出错?你第一个++ 函数 返回的是临时变量,同样的问题,你可以按照我上面写的那样 ,返回引用。 LeoSky 发表于 2017-10-9 16:53
还出错?你第一个++ 函数 返回的是临时变量,同样的问题,你可以按照我上面写的那样 ,返回引用。
是的,我试了,这回不是两个负数,而是两个267455040 release模式下是正确的,Debug模式下不正常,看来是VS的问题。 pk8900 发表于 2017-10-9 17:21
release模式下是正确的,Debug模式下不正常,看来是VS的问题。
不是VS问题 你把你修改后的代码贴出来。
页:
[1]
2