1

在 C++ 中调用函数时,会在后面写上函数名,()以将其区分为函数调用。为什么我不能以相同的方式调用流操纵器函数

为什么不允许这样做?:

cout << "Hello!" << endl();

不是endl变量持有\n吗?

谢谢!

4

3 回答 3

2

操纵器是专门设计用于与流对象上的插入 (<<) 和提取 (>>) 运算符结合使用的函数,例如:

cout << boolalpha;

它们仍然是常规函数,也可以像使用流对象作为参数的任何其他函数一样调用,例如:

boolalpha (cout);

所以,在你的代码中,你可以做

cout << "Hello!";
endl(cout);

代替

cout << "Hello!" << endl;

来源

于 2014-04-13T13:14:32.240 回答
2

流操纵器函数。因此,可以使用 call operator 来调用它们()。以下是您std::endl在流上调用的方式:

std::endl(std::cout);

这就是您要使用的每个流都必须调用它的方式std::endl。这是因为std::endl是一个函数,它返回一个对流对象的引用。这是一种非常古怪的方法,因此有一个方便的函数来简化语法:

std::ostream& operator<<(std::ostream& (*manip)(std::ostream&));

这是一个重载,operator<<()它的左侧有一个流,右侧有一个操纵器。std::endl从技术上讲是一个函数,因此可以将其转换为函数指针。

在这个重载的实现内部,manip几乎就是我刚刚向您展示的方式。这允许如下语法:

std::cout << "Hello, World" << std::endl;

如果您继续std::endl使用调用运算符进行调用,它将返回对流的引用。还有另一个operator<<()以 aconst void*作为参数的重载。那将是无意中调用的重载。

std::cout << std::endl(std::cout); // prints a newline then an address
于 2014-04-13T13:20:03.703 回答
1

endl 不是持有\n 的变量吗?

不它不是。std::endl是在全局命名空间中定义的函数

  template<typename _CharT, typename _Traits>
    inline basic_ostream<_CharT, _Traits>& 
    endl(basic_ostream<_CharT, _Traits>& __os)
    { return flush(__os.put(__os.widen('\n'))); }

在表达式std::cout << endl_or_something的右侧<<是调用的参数operator<<(第一个参数是std::ostream隐式的)。所以 endl_or_something 应该是 int、double 或其他可以转换为operator<<. 此运算符有一个重载版本,它接受指向函数的指针(函数引用std::ostream并返回对 的引用std::ostream):

  // [27.6.2.5] formatted output
  // [27.6.2.5.3]  basic_ostream::operator<<
  //@{
  /**
   *  @brief  Interface for manipulators.
   *
   *  Manipulators such as @c std::endl and @c std::hex use these
   *  functions in constructs like "std::cout << std::endl".  For more
   *  information, see the iomanip header.
  */
  __ostream_type&
  operator<<(__ostream_type& (*__pf)(__ostream_type&))
  {
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 60. What is a formatted input function?
// The inserters for manipulators are *not* formatted output functions.
return __pf(*this);
  }

由于std::endl签名匹配,因此可以在表达式中使用

std::cout << "Hello!" << std::endl;

或等效地

std::cout << "Hello!";
std::endl( std::cout);

但是请注意,当需要简单的换行符时,通常会错误地使用此操纵器,从而导致缓冲性能不佳。在这种情况下,只使用"\n".


为什么不允许这样做?:

cout << "Hello!" << endl();

std::endl 接受一个参数,std::ostream。您可以看到它可以通过以下方式调用:

return __pf(*this);

方法

return std::endl( *this); // std::endl( std::cout);

std::endl 没有不带参数的版本,因此可以使用

std::endl()

在表达

std::cout << std::endl;

它表示 的参数operator<<,它作为指向函数的指针传递,然后在 的主体中调用operator<<

于 2014-04-13T13:45:43.393 回答