为什么我们不应该对那些不接受C++论据的操纵者使用括号呢?
Why shouldn't we use parenthesis for manipulators that don't take arguments in C++?
例如,setw
接受一个整数参数,这意味着我们可以写setw(5)
,而left
和right
操纵符不接受任何参数。
-
为什么用
left()
和right()
代替left
和right
是错误的? -
带实参的操纵符和不带实参的操纵符有什么区别?
为什么使用left()和right()而不是left和right是错误的?
因为它无法编译!
它还会增加额外的函数调用,而没有任何好处。如果left
被作为一个函数调用,那么它必须返回一些与left
相同的目的,这将需要定义一个额外的类型和operator<<
的额外重载来处理该类型。何苦呢?
带实参的操作符和不带实参的操作符有什么区别?
接受参数的操作符是有状态的,它们返回一些存储参数的对象,然后使用这些参数来改变流状态,例如,对于每个接受参数的操作符,您有这样的内容:
struct SetW { int w; };
SetW
setw(int w) { return SetW{w}; }
ostream&
operator<<(ostream& out, SetW sw)
{
out.width(sw.w);
return out;
}
每个操纵符都有一个类似SetW
的类型,必须是这些类型中的每个类型的重载。
但是对于没有实参的操纵符,它们的定义(大致)如下:
ostream&
left(ostream& out)
{
out.str.setf(ios_base::left, ios_base::adjustfield).
return out;
}
,并且有一个重载处理所有这种形式的操作符,通过接受指向函数的指针作为实参:
using zero_arg_manipulator_type = ostream& (*)(ostream&);
ostream&
operator<<(ostream& out, zero_arg_manipulator_type f)
{
f(out);
return out;
}
这不需要像SetW
那样的额外类型,并且只需要一个重载来处理所有的零参数操纵符,因此更简单,代码更少。
如果您必须调用left()
,那么它需要返回一些自定义类型,如SetW
,因此必须为每个操纵符定义另一种类型,并且必须有更多的重载。这将使库复杂化,使其编译速度变慢,并可能使可执行文件变大变慢。
(为了回答这个问题,上面的细节被简化了,实际上函数是使用basic_ostream
而不是ostream
的模板,一些操纵符使用ios_base
或basic_ios
而不是basic_ostream ',但这并没有改变它如何工作的总体思想)。
这将是错误的,因为它不会工作:)-标准库是这样设计的,left()
将无法工作。
'无参数操纵符'只是函数(你可以自己调用它们,比如std::left(stream)
)(见这里)
有一个重载的operator<<
,它接受这些函数作为参数,允许编写out << std::left
,它将生成与std::left(out)
相同的代码。out << std::left
只是一个方便的符号。这也意味着您可以轻松地创建自己的操纵符。
在传递实际参数时,需要更复杂的代码,例如(不是实际示例,只是解释):
struct setw_t { int width; };
inline setw_t setw(int n) { return setw_t{n}; }
inline std::ostream& operator<<(std::ostream& out, setw_t t)
{
out.width(t.width);
return out;
}
因此,调用setw(5)
将产生更复杂的代码,但这并不奇怪,因为必须以某种方式传递5
。
允许写std::left()
(例如为了一致性)将需要创建许多这样的"标签结构",并且只会使添加新结构变得复杂。
- 条件断点在不应该触发时触发
- 你好。。。id_public变量不应该给出结果为 81 和 86 吗?为什么它为两个派生类占用不同的内存位置?
- 为什么我不应该把所有东西都放在标题中?
- 找不到 QRegularExpression 行为的任何解释。它有效,但不应该
- 在清除 istream 之前,我不应该需要取消获取它吗?
- c++ 为什么我不应该从不同的线程解锁互斥锁
- "typename"不应该只在模板函数或模板类中使用吗?
- 为不应该获得未定义行为的内容获取未定义的行为
- 两种情况下的输出不应该相同吗?
- 默认情况下,"std::shared_ptr"不应该使用"std::d efault_delete"吗?
- 错误代码 E0065 和 E0169 不应该有
- 矢量的值在不应该更改时更改
- 保证复制省略不应该适用吗?
- 不应该禁止访问私有类型吗?
- 使用匿名命名空间中的函数或另一个文件中的静态函数不应该出错吗?
- NRVO不应该保证局部命名变量和调用站点变量采用相同的地址吗?
- 类的私有成员在我的类实例化期间更改,即使他们不应该
- 为什么'system'不应该在 Windows 特定的应用程序中使用
- 正则表达式在我认为不应该在 c++ 中采用等号
- 为什么我们不应该对那些不接受C++论据的操纵者使用括号呢?