我正在考虑为一些数学类(矩阵、向量等)提供ostream运算符。一位朋友已经注意到,用于std::complex的ostream运算符的gcc标准库实现包括内部使用字符串流来格式化输出,然后再将其传递给实际的ostream
/// Insertion operator for complex values.
template<typename _Tp, typename _CharT, class _Traits>
basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os, const complex<_Tp>& __x)
{
basic_ostringstream<_CharT, _Traits> __s;
__s.flags(__os.flags());
__s.imbue(__os.getloc());
__s.precision(__os.precision());
__s << '(' << __x.real() << ',' << __x.imag() << ')';
return __os << __s.str();
}这种模式在boost中也很明显。我们正在尝试确定这是否是一个值得遵循的模式。有人担心,它涉及到包含字符串流的额外标头,并且在字符串流中需要额外的堆分配,这可能是可以避免的。
最合理的建议是,如果客户端需要该功能,那么他们可以创建字符串流并自行执行预传递。
谁能帮助我理解为什么这会被认为是好的实践,以及我是否应该采用它?
发布于 2012-10-16 05:23:14
考虑一下,如果在ostream上设置输出宽度,然后向其写入std::complex -您不希望宽度只影响第一个输出操作(即'('字符)
std::complex i(0, 1);
std::cout << std::setw(10) << std::left << i;这应该打印"(0,1) "而不是"( 0,1)"
通过将整个输出形成为单个字符串,然后将其写出,输出将遵循流上设置的字段宽度和其他格式化标志。
发布于 2012-10-16 05:26:43
在另一个响应中引用的线程化原因不会真正起作用:字符串仍然可以在流缓冲级分割,因为这些操作在从多个线程调用时不是原子的。
但是,有两个相关的考虑因素:
width()的含义是整个格式化字符串至少应该占用的字符数。如果在内部对另一个输出运算符使用输出运算符,则应该使第一个元素占据宽度,而不是生成由多个组件组成的整个字符串。例如,对于复数,实数元素将占用width(),而不是实数元素、逗号和虚数元素的组合。发布于 2012-10-16 05:22:10
此模式的一个主要目的是避免保留原始流的操纵器/标志,并在返回之前重新设置它们。Boost.IoStateSavers消除了这方面的需求,所以我想说使用这个库将是一个更好的实践。
https://stackoverflow.com/questions/12904155
复制相似问题