重载流操作符为什么必须用引用

转载 2011年07月20日 11:26:12

http://hi.baidu.com/%C8%CE%C5%E0%BB%A8/blog/item/1d3a1cf583a97e34bc310918.html


在C++中,流操作符(>>)是经常要被重载的,一般的形式是这样的:

class CObj
{
    ...
};

std::ostream& operator << (std::ostream& strm, const CObj& objA)
{
    ...
    return strm;
}

我们经常使用流的引用,而不是直接把一个流作为值传送,原因主要考虑到流是一种资源,如果作为值传送,出现了对资源的复制,释放的时候很麻烦,而且可能出现两个流同时操作一个文件的情况。但是这个原因只能说是我们用流作为引用而不是值传送的一个逻辑或性能限制,不是语法限制,也就是说,我们是可以硬把流作为一个值传送过来的。

也就是说,我们实际上可以这样写的:

class CObj
{
    ...
};

std::ostream operator << (std::ostream strm, const CObj& objA)
{
    ...
    return strm;
}

但是这样写了以后,编译器(Visual C++ 7.0)会报告编译时错误,类型不匹配。为什么会这样?难道是语法上有限制吗?

事实上是语法上并没有这样的限制说重载流符号的时候一定要用引用方式来传递流,事实上是,我们在传递参数的任何时候都必须用引用方式传递流,或者指针(这就和引用没区别了),原因在于:流的类体系结构中,不管是哪个流,都只有一个接收指针作为参数而且没有用explicit声明拷贝构造函数,也就是说,所有的流,都没有提供可以用另外一个流作为值传送参数的拷贝构造函数。这是不使用引用传送流引起语法错误的原因。

如果我们使用值传送来传递一个流给函数,那么在函数里要生成一个该流的临时变量,生成临时变量的时候,就要调用对应的拷贝构造函数,并且这个拷贝构造函数必须是以一个值传送的流作为参数的——但是流就是没有这样的拷贝构造函数。

结果,编译时错误就产生了!

 

WHY STREAM ONLY CAN BE PASSED AS REFERENCE WHEN OVERLOAD A STREAM OPERATOR?

In C plus plus, stream opeator (>>) is offen overloaded, and we always overload it like this:


class CObj
{
    ...
};

std::ostream& operator << (std::ostream& strm, const CObj& objA)
{
    ...
    return strm;
}


When we pass stream as a parameter to a function, we will use reference, not value passed,  the main reason is that stream is a kind of resource, if we pass it as a valued passed parameter, the programme will copy the resource, and then the resource which is copied twice may be releaseed twice too, and this, may cause trouble. For the more, copying a stream also can cause two or more streams write to one file at same time. But this is only a reason in the logic, not a grammer rule, that is to say, we can pass stream as valued passed parameter, althought this is wrong:

class CObj
{
    ...
};

std::ostream operator << (std::ostream strm, const CObj& objA)
{
    ...
    return strm;
}

If we really write like this, the compiler (I use Visual C++ 7.0) will report a compile-time error, type mismatch or construcor not found (I can't remember the actual one). Why? Is it a grammer rule?

In fact, it is not a grammer rule that you can not pass stream as value when you overload the stream operator, in fact, it is a grammer rule that we MUST pass stream as reference or pointer (pointer is reference, for the compiler) when we want to pass stream as a parameter to a function. The reason is: In the structure of stream's class, no matter which stream it is, it only have one copy constructor without explicit which can accept a pointer of stream, that is to say, all the streams, do not have a copy constructor which can accept another stream as a value. This is the reason which cause an error if we pass a stream as a value.

If we pass a stream as a value to a function, the function will create a temporer vaiable, the temperor variable is created by a copy constructor which can accept a stream as value, but all the streams do not have such a copy sonsturcutor.

Compile-time error occur as a result! 

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

 原因是: +,-,*等返回不了引用,比如+运算符,可以如下重载(为了简单,假设A 只有int x;int y) A operator+(A a,A b) {A sum;   sum...
  • csdnxq
  • csdnxq
  • 2015-05-02 21:38:45
  • 1372

一般操作符重载和friend重载

转自:http://linpder.blog.163.com/blog/static/487641020095231925257/ 运算符在重载的时候有两种方式,一是成员函数方式,二是成友元(frie...
  • herecles
  • herecles
  • 2010-12-10 17:12:00
  • 1736

下标运算符重载【】

#include using namespace std; class charArray { public: charArray(int len) { length = len; b...
  • nocodelife
  • nocodelife
  • 2013-03-01 10:56:38
  • 2943

为什么c++中重载流操作符要用友元函数

1.先来看看友元函数重载流操作符实例 2. 再来看看成员函数重载操作符实例 成员函数运行机理: 假如C1与C2d都为complex类,则,C1+C2被编译系统解释为C1.operator...
  • qq_35817700
  • qq_35817700
  • 2017-04-24 20:55:32
  • 444

对于c++中流操作符重载的理解

对于IO成员函数的重载不应该是一个成员函数的方式,并且应该声明为友元 一、如果为成员函数,都会有一个某人的参数,也就是this指针,为左操作数,下面考虑将其声明为成员函数的方式 对于cout 对于...
  • lightblueme
  • lightblueme
  • 2015-03-28 13:01:49
  • 902

关于重载赋值操作符需要返回引用

#include /* 如果赋值操作符不返回引用代码也能编译通过 但会增加调用copy构造函数的开销(因为返回局部对象会调用拷贝构造函数)。 返回引用的话能减少调用copy构造函数 (eff...
  • crazyacm
  • crazyacm
  • 2016-09-21 21:04:06
  • 531

流运算符为什么不能重载为成员函数,只能用友元函数重载

一、 为什么operator 如果是重载双目操作符(即为类的成员函数),就只要设置一个参数作为右侧运算量,而左侧运算量就是对象本身。。。。。。 而 >>  或 如果一定要声明为成员函数,只...
  • snowsnowsnow1991
  • snowsnowsnow1991
  • 2015-12-15 14:22:28
  • 2576

C++ 运算符流操作符重载和友元--笔记

/************************************************************************************************ *...
  • JarvisChu
  • JarvisChu
  • 2011-07-23 20:57:42
  • 5714

重载_流运算符和函数运算符()

重载流运算符来输入输出用户自己定义的类。 流运算符函数是全局函数,不能作为类的成员来定义。 声明:// 其中参数为流对象的引用,目标对象的引用。对于输出流,目标对象还要是常量。 istream& ...
  • qq_15015129
  • qq_15015129
  • 2016-11-25 15:45:49
  • 441

C++的流插入运算符“<<”和流提取运算符“>>”的重载

C++的流插入运算符“”是C++在类库中提供的,所有C++编译系统都在类库中提供输入流类istream和输出流类ostream。cin和cout分别是istream类和ostream类的对象。在类库提...
  • u010177286
  • u010177286
  • 2015-07-10 15:38:16
  • 2387
收藏助手
不良信息举报
您举报文章:重载流操作符为什么必须用引用
举报原因:
原因补充:

(最多只允许输入30个字)