我有以下代码:
#include <iostream>
using namespace std;
ostream& f(ostream& os) {
return os << "hi";
}
int main() {
cout << "hello " << f << endl;
return 0;
}
以某种方式运作 - 输出是“hello hi”。这是如何被编译器解释的?我不理解一个函数如何被插入到一个流中。
我有以下代码:
#include <iostream>
using namespace std;
ostream& f(ostream& os) {
return os << "hi";
}
int main() {
cout << "hello " << f << endl;
return 0;
}
以某种方式运作 - 输出是“hello hi”。这是如何被编译器解释的?我不理解一个函数如何被插入到一个流中。
std::ostream
有一个 operator<<
重载,它接收一个函数指针,该函数的签名与您编写的函数相似(参见此列表中的第11项):
basic_ostream& operator<<(
std::basic_ostream<CharT,Traits>& (*func)(std::basic_ostream<CharT,Traits>&) );
这个重载的作用是调用给定的函数并将自身作为参数传递。这个重载(以及其他几个类似的重载)旨在让您实现流操作符(stream manipulators),即通过 <<
输出到流中并从那里更改流状态的内容。例如,我们版本的(不正确的)普遍使用的 std::endl
可以这样实现:
std::ostream &myendl(std::ostream &s) {
s<<'\n';
s.flush();
return s;
}
这样就可以完全像“常规”的std :: endl
一样使用:
std::cout<<"Hello, World!"<<myendl;
(实际实现是模板化的,稍微复杂一些,因为它必须能够使用宽流来工作,但你已经明白了)
std::ostream::operator<<
有一个重载,它接受一个函数作为参数;该重载的主体是调用给定的函数。
实际上,这正是 endl
的工作方式。事实上,endl
实际上类似于以下函数:
ostream &endl(ostream &os)
{
os << '\n';
os.flush();
return os;
}
ostream
是 basic_ostream
的实例化这一事实)。据我所知,只有两个重载函数使用 ostream
和 ios_base
。 - Ulrich EckhardtCharT
和 Traits
。会进行编辑以澄清,因为你指出这一点有误导性。 - M.M
operator<<
可以接受一个函数并调用它。它究竟有多难理解? - n. m.std::endl
或std::flush
重载的工作方式也是如此。 - Ulrich Eckhardt