静态与成员运算符重载:标准::运算符<< 和 std::ostream::运算符<<
Static vs. Member Operator Overloads: std::operator<< and std::ostream::operator<<
C 的ostream
类为operator<<
提供了许多默认过载,但是它们并非全部以相同的方式定义。
char
类型,string
类型和RVALUE流的过载定义为免费的namespace
-Scope功能,例如:
namespace std {
ostream &operator<<(ostream &os, char c);
}
算术类型的过载,streambuf
和流操作器被定义为std::ostream
的成员函数,例如:
namespace std {
ostream &ostream::operator<<(int val);
}
我的问题
有这种区别的原因吗?我了解对这些操作员过载的调用略有不同(即免费的namespace
-Scope定义的ADL),因此我想可能会偏爱特定类型的操作员超载以进行优化。但是在这里,std::ostream
使用两种类型的定义用于不同类型。该语义上有任何优势或实现优化的优化吗?
我想可能会偏爱特定类型的操作员过载以进行优化
好吧,不。归根结底,两者都是作为函数调用的。对于超负荷分辨率本身,甚至没有明显的影响。由于该标准在[over.Match]上决定,第2段和6段:
如果任何操作数具有类别是类或枚举的类型, 用户定义的运算符函数可能会声明实现此处 操作员或用户定义的转换可能需要转换 操作数适用于适合内置操作员的类型。在这个 情况,超载分辨率用于确定哪个操作员功能 或内置运算符应调用以实现操作员。
超载分辨率的一组候选功能是 会员候选人,非成员候选人和内置的 候选人。参数列表包含所有操作数 操作员。一组候选功能的最佳功能是 根据[over.match.viable]和[over.match.best]选择。
所有这些操作员的过载都可以解决。唯一的语义差异是从ostream
派生的类可以选择 hide 某些成员过载。这是根据超载在派生类中的工作方式来完成的。只有明确声明的过载才适用。与这些成员不同,即使是从ostream
派生的类。
由于需要将派生类转换为ostream&
,以便选择自由功能过载,因此需要对其自身的隐式转换序列进行排名。如果所有过载都是免费功能,则可能会导致歧义。
因此,考虑因素很可能是将可能导致歧义(指针和算术类型)的类型分开,我们可能总是希望拥有可用的类型(对C串和单个字符的指针)。并允许隐藏"不太有用"的人以避免这些歧义。
正如W.F.指出的那样ostream
实际上是basic_ostream<char>
。免费功能恰好是仅需要流式传输的数据。流中的字符或字符串本机"字母"。因此,对于basic_ostream<wchar_t>
,这些免费功能将接受wchar_t
和wchar_t*
。简单的流很可能不需要任何访问流私有部分的访问。
其他过载是用于在流式传输之前序列化的数据。由于所述序列化与流的内部状态紧密相结合,因此使这些过载成为成员更有意义。
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 如何显式调用运算符<<
- 为什么COUT在朋友函数中不起作用,该功能超载了操作员&lt;&lt;这是一个iStream运算符
- C++运算符<<调用::ostream而不是std::osttream
- BOOST ::变体无法解决运算符&lt;&lt;对于STD :: Ostream
- 过载输出<<用于类的运算符,以打印其中的元组
- C++ostream:没有运算符匹配<<&应在'&'代币
- 重载运算符<<:此运算符函数的参数太多
- C++继承运算符<<
- 重载运算符<<用于模板类.即使使用好友关键字也无法获得私人会员
- 如何过载<<用于YAML::Emitter的运算符,以序列化包含另一个自定义类的向量的自定义类
- 为什么字符串流运算符<<擦除原始值
- 关于使用运算符<<为新手提供C++中的模板
- 我已经完成了<<运算符重载,但它'It’不起作用
- 重载运算符<<输出地址而不是数据成员
- 错误:没有匹配'运算符<<"在'std::cout
- 重载运算符<<用于ostream语法
- 当运算符<存在时,为什么要定义 LT?
- log4cxx访问异常,使用<<运算符和宏
- 重载<<运算符错误C2804:二进制'运算符<<'参数太多