重载运算符,后置++的问题,求解释。

重载运算符,后置++的问题,求解释。,第1张

按照你这样的后++方式,就不是自增的含义了,正确的方式是:

Complex Complex::::operator++(int)

{

Complexc = this;

++(this);//调用前++ (this)operator++()

return c;

}

myint++的返回值是一个const限定的右值,想要传引用的话在函数定义参数那行MyInteger前面加上一个const。

不加引用符号是按值传递,那么即便不打限定符const,改变传入参数的值也不会影响到原来的值,所以不加引用不会出错。

后缀++的原则是先取值,再自加,需要用中间值保存this对象原始值,自加完毕后,再返回这个中间值

const numCal numCal::operator++(int){

numCal temp(this);

for(int i(0);i<size;i++)arr[i]++;

return temp;

}

前面类体中的原型也改一改,返回值前加上const,避免像主函数中的后缀前缀一起用

重载的“=”有漏洞,也有内存泄漏,应该这样:

numCal&numCal::operator=(const numCal&num){

if (this != &num)

{

delete [] arr;

size=numsize;

arr=new int[size];

for(int i(0);i<numsize;i++)

arr[i]=numarr[i];

}

return this;

}

还有,主函数中的:

for(int i(0);i<6;i++)cout<<numarr[i]<<" ";这个arr是私有成员

for(int i(0);i<10;i++)cout<<numarr[i]<<" ";同上,这个i<10要改为i<9

num=++num3++;先后缀之后得到的是值,不能再前缀自加了,去掉前缀

C语言中,运算符除了常见的三大类,算术运算符、关系运算符与逻辑运算符之外,还有一些用于完成特殊任务的运算符。

运算符的运算优先级共分为15 级,1 级最高,15 级最低。 在表达式中,优先级较高的先于优先级较低的进行运算。而在一个运算量两侧的运算符 优先级相同时,则按运算符的结合性所规定的结合方向处理。

一级运算符:标识,常量,字符串文字量,优先级提升表达式最优先执行。

二级运算符:数组下标运算(expression)、函数调用(argument-expression-list)、成员访问(identifier、 -> identifier)、后缀自增(i++)、后缀自减(i--)、 复合初始化(initializer-list)。

三级运算符:前缀自增(++i)、前缀自减(--i)、单目转型表式式(取地址& ,提领 , 正号+ ,负号-、 位反~ 逻辑否!)、求类型长度(sizeof unary-expression)。

四级运算符:强制表达式成为type-name指定的类型( type-name ) cast-expression。

五级运算符:“ ” 乘法运算符。

六级运算符:“ + ”加法运算符。

七级运算符:<< 左移运算符;>> 右移运算符。

八级运算符:<、<=、>、>=关系运算符。

九级运算符:“ == ”等于运算符;“ != ”不等于运算符。

十级运算符:“ & ”按位与运算符。

十一级运算符:“ ∧ ”按位异或运算符。

十二级运算符:“ | ”按位或运算符。

十三级运算符:“&&”逻辑与运算符。

十四级运算符:“ || ”逻辑或运算符。

十五级运算符: :条件运算符。

扩展资料

C语言中各运算符的结合性:

1、左结合性(自左至右):

例如算术运算符的结合性是自左至右,即先左后右。如有表达式x-y+z 则y 应先与“-”号结合,执行x-y 运算,然后再执行+z 的运算。这种自左至右的结合方向就称为“左结合性”。

2、右结合性(自右至左)

自右至左的结合方向称为“右结合性”。最典型的右结合 性运算符是赋值运算符。如x=y=z,由于“=”的右结合性,应先执行y=z 再执行x=(y=z)运算。C语言运算符中有不少为右结合性,应注意区别,以避免理解错误。

——C语言运算符

我知道问题出在哪,但是这个BUG逻辑,我确实没算出来。。。是因为实在太难了。。

输出错误的原理在于,++,--和<<的优先级上。

C++的符号优先级是C语言的优先级一样的,所以<<虽然被cout用于重载输出用,但是实际上还是左移运算符的优先级,然而<<左移运算符的优先级比++,--的优先级都低,所以先做++,--,然后才输出,因为输出有多个<< 这样的左移运算符,所以输出是按从做到右的顺序做的,然而输出前的++,--确实先做的,而且++,--优先级高,然后最大的BUG就出现了,因为++,--的运算,是右边的先做,然后在做左边的,所以第一个输出3。

因为输出第一个d++的时候,是先从最右边的--d开始的,然后做d--,再做++d,最后才是输出第一个d++,这时候,先输出d,所以这个时候的值是3,然后自增的,所以第二个就是4,至于后面两个,就触发BUG了,d到底是多少啊?按道理,后面的两个d--,--d的运算早就做了,输出的时候应该是直接输出d的值的,然而也不是,已经搞不清楚编译器面对这样的BUG是怎么处理的了。。只能判断出前两个,第一个是3没错,做完直接++了,所以第二个输出4,因为第二个++d,根本不做++了,++早就在输出第一个值之前做完了,应该直接输出第一个运算之后的d的值,同理第三,第四,也应该是同一个值,但是却不是。。。已经搞不清楚编译器是怎么处理的了。。。

解决方法:你的本意就是从左向右一个一个输出,但是<<运算符的优先级太低了,所以只要一个一个的加上括号,保证每个d++,--d这样的运算做完,马上保证<<输出运算符的优先级,即可不会触发这个BUG,即应该改成((((cout<<d++)<<++d)<<d--)<<--d)<<endl;

即可保证输出都是正确的,每次都是先做第一个++,--操作后,马上<<进行输出,结果之间不会干扰。

这样的BUG,就像C语言里的C=C+C++,这样的BUG,C语言里,这样的程序也是会出BUG的,因为C+C++这样的运算,又要用到变量C的值,却又对变量C的值进行了更改,结果是很危险的。。。你这里的BUG和C语言里这样的BUG是同一个原理。。。。

运算符重载,虽然是重定义运算符函数;

但是不能违背运算符原来的基本性质;

而++是一元操作符,即隐含的this指针;

而多出的Int只是为了区分前自增和后自增,并没有其他用处。

a=a+3i; //使用了系统合成的赋值操作符

赋值操作符、copy构造函数、析构函数被称为类的复制控制。当类中存在指针数据成员时,通常

必须重定义类的复制控制,而不能使用系统合成的复制控制;除非,你不使用复制控制。很显然

在上面的语句中,你运用了系统合成的赋值操作符

分析a=a+3i; 这句代码。

首先,调用+操作符的重载函数,在集合a中添加了3i这个元素;

然后,调用合成赋值操作符函数Set& operator = (const Set &);a自己给自己赋值。

函数返回对a的引用,即返回a自己。

分析

Set& Set::operator |(Set &s) //并集

{

Set temp(Size+sSize);

……

return temp;

}

你返回了temp这个局部变量的引用,这是错误的,因为在该函数执行完毕以后,temp就被撤销

了(即系统自动调用了temp的析构函数)。所以你只要在程序中写了析构函数,你的程序就会

出错。那应该怎么办呢?返回Set类型就可以了,这就意味着使用a|b这句代码地方,系统会定

义一个没有名字的临时变量(假设它的名字为T),并且用返回值temp来初始化这个临时变量。

即相当于调用了你定义的copy构造函数T(a|b);

分析

d=a|b;这句代码。

首先:

同样使用a|b这句代码地方,系统会定义一个没有

名字的临时变量(假设它的名字为T),并且用返回值temp来初始化这个临时变量。即相当于调

用了你定义的copy构造函数T(a|b);

然后:

调用了系统合成的赋值操作符函数,其实合成的构造函数就是下面的这个函数:

Set& operator = ( const Set &r )

{

Size = rSize;

Elems = rElems;

Num = rNum;

}

调用上面函数的结果是把T这个临时变量的Elems(它是一个指针)的值直接赋给了d的Elems成

员变量,然后系统就会撤销T这个临时变量(即调用T的析构函数),这样d的Elems将成为一个

悬垂指针。悬垂指针指向曾经存放对象的内存,但是该对象已经不再存在了。悬垂指针往往导致

程序错误,而且很难检测出来。

可以看出,你的程序必须定义自己的赋值操作符函数。这样才能正确执行d=a|b;这句代码。

下面是赋值操作符函数:

Set& Set::operator= ( const Set &r )

{

Size = rSize;

Num = rNum;

if ( this != &r )

{

Elems = new int[Size];

}

else

{

return this;

}

for ( int i = 0; i < Num; i++ )

{

Elems[i] = rElems[i];

}

return this;

}

花了我好长时间,你应该请我吃饭阿

欢迎分享,转载请注明来源:浪漫分享网

原文地址:https://hunlipic.com/meirong/10377955.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-11-04
下一篇2023-11-04

发表评论

登录后才能评论

评论列表(0条)

    保存