C++运算符重载,+-*/的重载,返回值为什么是对象而不是对象的引用?而流操作符<< 和 >> 却返回的是引用?

如题所述

原因是:

    +,-,*等返回不了引用,比如+运算符,可以如下重载(为了简单,假设A 只有int x;int y)

    A operator+(A a,A b) {A sum;   sum.x=a.x+b.x; sum.y=a.y+b.y;   return sum; }

    分析不能用引用的原因: 函数传入了两个参数a,b,并且+只能传入两个参数(c++不允许自己创造运算符),这样就限定了和sum不能作为参数传入,所以sum只能是一个函数里的临时变量,但是临时变量在函数结束时是要销毁的,那么函数调用玩,sum就没有了, 如果返回引用,引用源都已经没有了,还怎么引用,引用哪里的东西呢??

    所以不能引用。

    <<,>>可以返回引用,而且不返回引用也是编译不过的,貌似是c++的要求。可以不用引用试一试,有的编译器会出来一个ios_base.h文件,就是想告诉你用引用。

    返回引用也是可以解释的。 比如还是上面的A类型,如下

    ostream& operator<<(ostream& out, const A& a) { out<<A.x<<' '<<A.y<<endl; retrun out;}

    能返回引用,首先是因为out是作为参数传入的,不是函数的临时变量,函数结束时它仍然存在,这样就可以引用了。  再者,返回引用效率高,不用拷贝一个新的,直接返回它自己。 而且,返回引用有助于连着调用。比如cout<<a<<b<<c<<d,为什么可以连着写?其实<<也是函数,为什么我们平时的函数一般不能连着写?如a.xx().xx().xx.()这样调用三个xx()。这也体现了引用的作用。 对于cout<<a<<b<<c<<d;就是

    operator<<(operator<<(operator<<(operato<<(cout,a),b),c),d);

    从左到右先执行cout<<a执行完了后返回cout的引用,就是cout本身,那么原式变为cout<<b<<c<<d; 紧接着这行cout<<b执行完再次返回cout........这样就把a,b,c,d依次作用到了cout,我们于是看到abcd连续输出了。

追问

如你所说,cout<<a<<b<<c<<d;谭浩强说,先执行cout<<a,返回一个输出流对象(引用),然后这个新的cout对象(引用)又执行<<b,然后又返回一个新的cout对象(引用),直到输出完成。每输出一次,就返回一个新的输出流对象(引用),那每次输出流对象cout有啥不同。

追答

一般可以认为第一次执行完cout直接将a输出到了屏幕,cout本身没有变化,然后执行b......

但是具体情况不是这样的。这要看c++的IO具体是怎么设计的。执行一次cout<<a并不一定直接将a输出到屏幕,而是将a转到IO的缓冲区,具体什么时候将a输出到屏幕要看系统什么时候有时间和c++的IO具体是怎么实现的。 系统掌握着消息队列,每次从里面抽取一条消息执行,因为CPU效率很高,我们感觉程序是连续运行的,其实不连续。对于多核处理器来说可以发生真实的同时执行几个程序。

要强制系统将数据输出到屏幕上,可以“刷新”一下,比如用cout<<endl;就是打一个换行,再刷新缓冲区,刷到屏幕上。


对于评论区的两点,解释一下:

    重载<<流输出运算符,我是用于一个自定义类与ostream类,不是重载<<的移位运算等,不用做其他用法。  在我的编译器上不通过(VS2012和DEV c++都编译不通过)

    我举得例子有错误,为了简便直接写的,现在发现是错的。因为都是A的对象相加,如果有两个参数,那么应该是友元函数,frined ......, 如果一个参数,可以声明为成员函数。

    至于为什么返回引用也正常,这是由于:

    “函数返回的临时变量是放在堆栈上的,所以返回来后如果你没有调用其他的函数,那么这个临时变量在依然保存在堆栈中,是可以被引用的。
    因为这时堆栈并没有被破坏。但是一旦调用其他函数后堆栈被破坏了,那个返回值就没有用了”

    摘自“正心修身齐家治国平天下”的百度空间,可以看一下。

    即使这样编译器也会给警告(WARNING),不建议这么写

温馨提示:内容为网友见解,仅供参考
第1个回答  2013-09-30
C++ Primer里有解释的,一切是为了保持与内置操作的一致性,并非一定要这样,只是这样做才是规范的,还是那句话保持与内置操作的一致性!!!
第2个回答  2013-09-30
你可以认为在函数中产生了新的对象,并且需要返回的就是新产生的这个对象,就返回对象;
如果在函数中没有产生新的对象,需要返回的是调用函数之前就存在的对象,就返回引用。
第3个回答  2013-09-30
如果返回的是引用,那么a+b=5这样的表达式你说怎么理解?
返回怎样的值,是基于需求考虑的,+-*/的结果,只需要临时使用,因此,返回对象就行了,至于返回引用,可以一方面可以继续处理,另一方面,没有复制拷贝的代价,更高效。

...而不是对象的引用?而流操作符<< 和 >> 却返回的是引用?
分析不能用引用的原因: 函数传入了两个参数a,b,并且+只能传入两个参数(c++不允许自己创造运算符),这样就限定了和sum不能作为参数传入,所以sum只能是一个函数里的临时变量,但是临时变量在函数结束时是要销毁的,那么函数调用玩,sum就没有了, 如果返回引用,引用源都已经没有了,还怎么引用,...

c++重载后置++运算符为啥传入引用会报错??
myint++的返回值是一个const限定的右值,想要传引用的话在函数定义参数那行MyInteger前面加上一个const。不加引用符号是按值传递,那么即便不打限定符const,改变传入参数的值也不会影响到原来的值,所以不加引用不会出错。

C++中为什么重载前置++运算符要加个&?
1、因为重载自加运算符后可以返回对象的引用, 以方便在表达式中连续使用。举个例:cout<<是经常用的,其实是重载了<<这个操作符。如果不返回引用,cout<<a<<b<<endl; 就不可以一起写了。如果返回自身的引用 cout<<a之后,返回身身的引用,后面可以继续接b了。就是这个意思吧。好多重载操作符,...

c++中的重载运算符<<和>>为什么是只可以为友元函数,不可是成员函数?我...
如果是重载双目操作符(即为类的成员函数),就只要设置一个参数作为右侧运算量,而左侧运算量就是对象本身。。。而 >> 或<< 左侧运算量是 cin或cout 而不是对象本身,所以不满足后面一点。。。就只能申明为友元函数了。。。如果一定要声明为成员函数,只能成为如下的形式:ostream & operator<<(os...

C++重载运算符时为什么有时候需要用&,请举个形象点的例子
因此,返回一个流对象引用是惟一选择。这个唯一选择很关键,它说明了引用的重要性以及无可替代性,也许这就是C++语言中引入引用这个概念的原因吧。 赋值操作符=。这个操作符象流操作符一样,是可以连续使用的,例如:x = j = 10;或者(x=10)=100;赋值操作符的返回值必须是一个左值,以便可以被继续...

C++重载=,+=等时候为什么要用返回引用
就像上面为什么我可以连用两次<<操作符?如果不是返回引用,第二次插入操作将会将b插入到那个临时的流对象,而将会显示的会是那个全局的流,所以就看不到b了。就正如我们程序开始申请一个全局全量;int g_INT;有个函数会定时输出它的值。到处都可以操作它。如果一个函数操作它,而又希望它的返回也...

c++中运算符(\\" << \\")重载ostream&是什么意思
运算符重载,是对现有操作符使用于自定义用户类型的一种扩展,但具体的性质不能变,如<<表示流操作符左侧对象为流的本质不能变,+为两元操作符本质不能变,再如,对于->重载必须返回指针类型不可变!即,即使进行运算符重载,也只是有限自由!friend ostream & operator << (ostream &os, const C...

C++运算符重载:为什么流运算符不能重载为成员函数?
不能重载的根本原因在于,大部份的标准库实现中,对ostream,istream类体系采用了构造函数保护继承的方式。。。致使即使以继承的方式来扩展流类,也会在对象实例化时遭遇阻碍。。。另一方面,标准库中的流类,其插入符函数没有声明为虚函数,因此子类不能对其实现进行覆盖,所以也使成员函数重载遭遇到实质...

在C++中运算符重载的时候究竟什么时候应该加引用,什么时候不应该加引...
如果返回值会被赋值,就必须返回引用,例如=重载\\x0d\\x0a如果返回值是一个局部变量,就一定不能返回引用,例如+重载\\x0d\\x0a如果为了提高效率,参数可以使用引用,\\x0d\\x0a而[]的实际参数经常是一个常量,常量你是无法引用,所以不能用引用作为[]的参数。

c++ 运算符重载 return *this是什么意思?
因此C++运算符重载反回的是什么,要根据反回类型来决定的,不是都一味的反回returen *this就行的,但一般的操作符重载函数都是以const A& operator +(A & m)的形式开始的,基本上都要求反回对自身的引用,注意是对自身类的引用,不一定要*this,也可以是new A()之类的类A的对象,之所以要使用...

相似回答