在 C++ 中调用函数时,会在后面写上函数名,()
以将其区分为函数调用。为什么我不能以相同的方式调用流操纵器函数?
为什么不允许这样做?:
cout << "Hello!" << endl();
不是endl
变量持有\n
吗?
谢谢!
在 C++ 中调用函数时,会在后面写上函数名,()
以将其区分为函数调用。为什么我不能以相同的方式调用流操纵器函数?
为什么不允许这样做?:
cout << "Hello!" << endl();
不是endl
变量持有\n
吗?
谢谢!
操纵器是专门设计用于与流对象上的插入 (<<) 和提取 (>>) 运算符结合使用的函数,例如:
cout << boolalpha;
它们仍然是常规函数,也可以像使用流对象作为参数的任何其他函数一样调用,例如:
boolalpha (cout);
所以,在你的代码中,你可以做
cout << "Hello!";
endl(cout);
代替
cout << "Hello!" << endl;
来源。
流操纵器是函数。因此,可以使用 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
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<<
。