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

转载 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! 

操作符重载之解引用与箭头操作符

箭头操作符与众不同。它可能表现得像二元操作符一样:接受一个对象和一个成员名,对对象解引用以获取成员。不管外表如何,箭头操作符不接受显式形参。这里没有第二个形参,因为 -> 的右操作数不是表达式,相反,...
  • IT_PCode
  • IT_PCode
  • 2015年01月13日 18:02
  • 1281

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

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

赋值运算符重载函数 返回引用和返回对象的区别

赋值重载符的定义 返回引用和返回对象的区别#include "stdafx.h" #include using namespace std;class CStudent { public: C...
  • miyunhong
  • miyunhong
  • 2016年04月14日 10:19
  • 1369

重载输入输出运算符引用的理解

#include classcoord{ int x,y; public: coord(int i=0,int j=0) {            x=i;            y=j...
  • gaomyf
  • gaomyf
  • 2014年08月24日 12:25
  • 593

map/set容器的运算符重载比较函数的易错点

//观察下列程序 //Sample Input: /* 5 aa 89 bb 76 cc 87 dd 89 ee 76 */ //你觉得会输出什么??? #include #include #i...
  • u012823258
  • u012823258
  • 2015年05月27日 17:23
  • 901

C++ STL 基础及应用(2) 模板与操作符重载

模板是 C++ 语言中重要的概念。它提供了一种通用的方法来开发重用的代码,即以创建参数化的 C++ 类型。 本章将阐述一些具体的 STL 模板思想,并简单介绍操作符重载与模板的联系。 文中将给出一个简...
  • Raito__
  • Raito__
  • 2016年05月22日 17:13
  • 2549

C++运算符重载(11) - 重载<<和>>操作符

运算符 “>”用于流输出。 在开始重载这些操作符之前,必须注意下面的事项: 1) cout是输出类的对象,而cin是输入类的对象 2) 这些操作符必须重载为全局函数。如果想要让它们可以访问私有成员,...
  • shltsh
  • shltsh
  • 2015年05月27日 00:11
  • 760

探索Scala(1)-- 运算符重载

Scala语言运算符重载完全是语法层面的小把戏,本文记录我对Scala语言运算符重载的一些理解...
  • SpiderDog
  • SpiderDog
  • 2014年10月14日 14:39
  • 3312

Kotlin操作符重载(十)

Kotin操作符重载
  • learningITwell
  • learningITwell
  • 2017年06月08日 20:16
  • 278

C++运算符重载(4) - 不能被重载的操作符

C++,中,下面的操作符是不能被重载的: . (成员访问或点操作符) ?: (三元操作符或条件操作符) :: (范围操作符) .* (指向成员的指针操作符) sizeof (取对象大小操作符) typ...
  • shltsh
  • shltsh
  • 2015年05月26日 09:39
  • 2114
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:重载流操作符为什么必须用引用
举报原因:
原因补充:

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