std::endl的结构

7
我是新手,对C++不熟悉,对于 std::endl 感到困惑。在尝试理解 std::endl 是什么时,我发现有些资源告诉我它是一个函数。
然而,一个函数怎么可能没有括号呢?请帮我解答这个问题。

5
函数和函数调用是有区别的。 - molbdnilo
1
没有括号的函数就像没有+的整数,或者没有[]的数组,或者没有printf的字符串。你可以将它传来传去,把它放在一边,然后当它的时间到来时,你就会取回它,并将它放在参数列表的前面。(从技术上讲,你正在传递一个函数指针或引用,但此时此刻这并不重要)。 - n. m.
3个回答

6

阅读参考文献

std::endl

插入一个换行符并刷新流。

它与流一起使用,例如 std::cout

它不是一个函数,而是一个函数模板。

没有括号的 std::endl 是指一组重载函数 - 所有可能的特化该函数模板的函数。在如何使std::endl不使用任何括号成为函数?中了解更多信息。


即使是函数模板,它仍然是一个函数,OP问为什么不需要将其称为std::endl() - Amadeus
1
@gsamaras,你的回答非常快 :) - Ishpreet
我在@ishpreet发帖的时候看到了它!=) - gsamaras

4
然而,一个函数怎么可能没有括号呢?
一个函数名后面不跟随 () 只是对该函数的引用。这与其他任何类型完全相同:
void foo(int) {}

char x = 'a';

char *p = &x;

int main()
{
  p;  // Refers to p
  *p; // Dereferences p (refers to whatever p points to)
  foo;  // Refers to foo
  foo(42); // Calls foo
}

std::endl是一个函数(实际上是一个函数模板),它接受一个类型为“流”的参数,并通过向该流中插入EOL表示并刷新它来工作。如果你想要,你实际上可以像使用任何其他函数一样使用它:

std::endl(std::cout);

谜题的最后一块拼图是标准库提供了一个重载(再次,一个模板)operator<<,使得LHS参数是流,RHS参数是函数;这个运算符的实现调用RHS参数(函数)并将LHS参数(流)传递给它。从概念上讲,就像这样:

Stream& operator<< (Stream &s, const Function &f)
{
  f(s);
  return s;
}

因此,调用 std::cout << std::endl 会调用该运算符重载,该运算符重载反过来会调用 std::endl(std::cout),它执行EOL插入和刷新操作。
至于哪种形式应优先选择(直接调用与<<操作符),肯定是使用<<。这是惯用法,而且可以在单个表达式中轻松组合多个流操作符。像这样:
std::cout << "Temperature: " << std::fixed << std::setprecision(3) << temperature << " (rounds to " << std::setprecision(1) << temperature << ')' << std::endl;

调用 std::cout << std::endl(std::cout) 会报错,或者是我做错了什么? - Arrrow
1
@Arrrow 尝试使用 std::endl(std::cout); 代替 std::cout << std::endl; 作为单个语句。 - Bob__
2
@Arrrow,你试图将std::endl(std::cout)函数的返回值发送到流std::cout中,而这是流引用,所以你正在做类似于std::cout << std::cout的事情,并通过endl函数向流发送EOL。也就是说,这并没有太多意义。 - Ped7g
值得注意的是,使用流操作符的原因在于它们可以轻松地与“operator <<”组合使用,例如“std::cout <<“温度为”<< std::fixed << std::right << std::setw(5) << std::setprecision(2) << temperature << std::endl; ”;对于直接函数调用,您始终需要使用多个语句或“operator,”以避免排序问题。 - Arne Vogel
@ArneVogel 好观点,谢谢。我会在有时间的时候将其纳入答案中(可能是明天)。 - Angew is no longer proud of SO
显示剩余5条评论

0

endl是一个仅用于输出的I/O操作符。

endl是一个仅用于输出的I/O操作符,可以通过表达式out << std::endl来调用任何类型为std::basic_ostream的输出流。

将换行符插入到输出序列os中,并刷新它,就好像调用os.put(os.widen('\n'))后紧接着调用os.flush()一样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接