为什么我们需要在重载 >> 和 << 运算符时 return 引用 istream/ostream?
Why we need to return reference to istream/ostream while overloading >> and << operators?
如果我不 return din
或 dout
会发生什么,实际上我正在读一本书,其中作者 return 的回流引用
istream & operator>>(istream &din,vector &a)
{
for(int i=0;i<size;i++)
din>>a.v[i];
return din;
}
ostream & operator<<(ostream &dout,vector &a)
{
dout<<"("<<a.v[0];
for(int i=1;i<size;i++)
dout<<", "<<a.v[i];
dout<<")";
return dout;
}
在这种情况下,当返回引用时,您可以将运算符组合成一个链。例如
std::cout << "Hello " << "Rajat Verma";
这相当于运营商的以下调用
operator <<( operator <<( std::cout, "Hello" ), "Rajat Verma" );
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
returns reference to std::cout
另一件事是 ostream 和 istream 标准对象(例如 cout 和 cin)使用私有复制构造函数,因此它们应该通过引用而不是值返回
原因是几个事实的结合。
您希望能够像
那样链接输入和输出操作
in >> x >> y;
out << z << std::precision(10) << t << std::endl;
所以你必须 return 再次允许 operator<<
的东西。
因为您希望您的运算符在任何 istream
上工作,即从 std::istream
派生的任何对象,您不能定义
operator<<(istream_type, object); // take istream by value
因为这只适用于特定的 istream 类型 istream_type
,但不适用于通用的 istream
。为此必须使用多态性,即采用引用或指针(这将是对从 std::istream
派生的 class 的引用或指针)。
因为你只有对 istream 的引用,你不能 return istream 对象本身(它可能是在 operator<<
) 但只有你得到的参考。
可以通过定义 operator<<
和 template
并按值取 return 和 istream_type
来绕过此限制,但这需要 istream
type 有一个复制构造函数,它可能有充分的理由没有。
为了激发多态性,原则上可以使用指针(指向流)而不是引用。但是,operator<<(stream*,const char*)
是
在 C++ 中不允许(至少一个操作数必须是 class 或枚举类型)。
因此,对于流指针,必须使用函数调用语法,而您又回到了 C 风格 fprintf(stream*, args...)
。
此外,指针可以为 null 或 dangling,这实际上是它们的默认状态(当没有初始化器声明时),而引用可以假定为有效(没有初始化器不能声明它)。
当您键入:
cout << 向量;
cout 具有 ostream 类型,因此当您使用“<<”时,它确实需要 return 与 ostream 类型的争论才能使 cout 工作
如果我不 return din
或 dout
会发生什么,实际上我正在读一本书,其中作者 return 的回流引用
istream & operator>>(istream &din,vector &a)
{
for(int i=0;i<size;i++)
din>>a.v[i];
return din;
}
ostream & operator<<(ostream &dout,vector &a)
{
dout<<"("<<a.v[0];
for(int i=1;i<size;i++)
dout<<", "<<a.v[i];
dout<<")";
return dout;
}
在这种情况下,当返回引用时,您可以将运算符组合成一个链。例如
std::cout << "Hello " << "Rajat Verma";
这相当于运营商的以下调用
operator <<( operator <<( std::cout, "Hello" ), "Rajat Verma" );
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
returns reference to std::cout
另一件事是 ostream 和 istream 标准对象(例如 cout 和 cin)使用私有复制构造函数,因此它们应该通过引用而不是值返回
原因是几个事实的结合。
您希望能够像
那样链接输入和输出操作in >> x >> y; out << z << std::precision(10) << t << std::endl;
所以你必须 return 再次允许
operator<<
的东西。因为您希望您的运算符在任何
istream
上工作,即从std::istream
派生的任何对象,您不能定义operator<<(istream_type, object); // take istream by value
因为这只适用于特定的 istream 类型
istream_type
,但不适用于通用的istream
。为此必须使用多态性,即采用引用或指针(这将是对从std::istream
派生的 class 的引用或指针)。因为你只有对 istream 的引用,你不能 return istream 对象本身(它可能是在
operator<<
) 但只有你得到的参考。可以通过定义
operator<<
和template
并按值取 return 和istream_type
来绕过此限制,但这需要istream
type 有一个复制构造函数,它可能有充分的理由没有。为了激发多态性,原则上可以使用指针(指向流)而不是引用。但是,
operator<<(stream*,const char*)
是 在 C++ 中不允许(至少一个操作数必须是 class 或枚举类型)。因此,对于流指针,必须使用函数调用语法,而您又回到了 C 风格
fprintf(stream*, args...)
。此外,指针可以为 null 或 dangling,这实际上是它们的默认状态(当没有初始化器声明时),而引用可以假定为有效(没有初始化器不能声明它)。
当您键入: cout << 向量; cout 具有 ostream 类型,因此当您使用“<<”时,它确实需要 return 与 ostream 类型的争论才能使 cout 工作