std::ostringstream
calls vsnprintf
两次:第一次尝试使用小缓冲区,第二次尝试使用正确大小的缓冲区。看locale_facets.tcc
1011 号线附近(这里std::__convert_from_v
是一个代理vsnprintf
):
#if _GLIBCXX_USE_C99_STDIO
// Precision is always used except for hexfloat format.
const bool __use_prec =
(__io.flags() & ios_base::floatfield) != ios_base::floatfield;
// First try a buffer perhaps big enough (most probably sufficient
// for non-ios_base::fixed outputs)
int __cs_size = __max_digits * 3;
char* __cs = static_cast<char*>(__builtin_alloca(__cs_size));
if (__use_prec)
__len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
__fbuf, __prec, __v);
else
__len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
__fbuf, __v);
// If the buffer was not large enough, try again with the correct size.
if (__len >= __cs_size)
{
__cs_size = __len + 1;
__cs = static_cast<char*>(__builtin_alloca(__cs_size));
if (__use_prec)
__len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
__fbuf, __prec, __v);
else
__len = std::__convert_from_v(_S_get_c_locale(), __cs, __cs_size,
__fbuf, __v);
}
这完全符合观察结果,即对于小要求的精度性能与snprintf
,而对于更高的精度,它会差两倍。
此外,由于使用的缓冲区不依赖于任何属性std::ostringstream
缓冲区,仅在__max_digits
,定义为__gnu_cxx::__numeric_traits<_ValueT>::__digits10
,除了修复之外似乎没有任何自然的解决方法libstdc++
itself.
I've reported它是 libstdc++ 的错误。