【问题标题】:Structure of std::endl [duplicate]std::endl 的结构 [重复]
【发布时间】:2018-03-02 17:28:49
【问题描述】:

我是 C++ 新手,我对 std::endl 感到困惑。在尝试了解 std::endl 是什么时,我遇到了一些资源,这些资源告诉我它是一个函数。

但是,函数怎么能没有括号呢?

【问题讨论】:

  • 函数和函数调用是有区别的。
  • 一个没有括号的函数就像一个没有+的整数,或者一个没有[]的数组,或者一个没有printf的字符串。你传递它,把它放在一边,然后当它到来的时候,你检索它并将它放在一个参数列表的前面。 (从技术上讲,您正在使用函数指针或引用,但此时这并不重要)。

标签: c++ c++-standard-library endl


【解决方案1】:

阅读ref

std::endl

插入换行符并刷新流。

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

不是函数,是函数模板。

std::endl 不带括号是指一组重载函数 - 该函数模板的所有可能的特化。阅读更多How does std::endl not use any brackets if it is a function?

【讨论】:

  • 即使是一个函数模板,它仍然是一个函数,OP问你为什么不需要把它称为std::endl()
  • @gsamaras 你回答得很快 :)
  • 我在@ishpreet 发帖时看到了! =)
【解决方案2】:

但是,函数怎么能没有括号呢?

函数的名称,后面没有(),只是对该函数的引用。它与任何其他类型完全相同:

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 &lt;&lt; std::endl 会调用该运算符重载,而该运算符重载又会调用 std::endl(std::cout),后者执行 EOL 插入 + 刷新。

至于首选哪种形式(直接调用与&lt;&lt; 运算符),肯定是&lt;&lt; 的使用。它是惯用的,并且它允许在单个表达式中轻松组合多个流操纵器。像这样:

std::cout << "Temperature: " << std::fixed << std::setprecision(3) << temperature << " (rounds to " << std::setprecision(1) << temperature << ')' << std::endl;

【讨论】:

  • 调用std::cout &lt;&lt; std::endl(std::cout) 会出错,还是我做错了什么?
  • @Arrrow 尝试使用 std::endl(std::cout); 而不是 std::cout &lt;&lt; std::endl; 作为单个语句。
  • @Arrrow 您正在尝试将std::endl(std::cout) 函数的返回值发送到流std::cout,这就是流引用,所以您正在执行类似std::cout &lt;&lt; std::cout 的操作,中间还会发送EOL 到endl 函数的流。 IE。没有多大意义。
  • @Bob__ 啊,所以这与 std::cout 具有相同的功能
  • @Arrrow 我从来没有说过在任何地方调用std::endl(std::cout) 的结果流式传输。就像一个普通的旧函数一样调用它。
【解决方案3】:

endl 是一个仅输出 I/O 操纵器。

endl 是一个仅输出 I/O 操纵器,它可以使用诸如 out &lt;&lt; std::endl 之类的表达式来调用任何类型为 std::basic_ostream 的类型。

在输出序列 os 中插入一个换行符并刷新它,就像调用 os.put(os.widen('\n')) 后跟 os.flush() 一样。

【讨论】:

    猜你喜欢
    • 2020-03-19
    • 2011-01-13
    • 2012-03-27
    • 2013-08-16
    • 1970-01-01
    • 1970-01-01
    • 2012-01-08
    • 2015-04-19
    相关资源
    最近更新 更多