一个选项是让临时缓冲区启动一些已知的大小,然后增加它,如果看到它不足以
vsnprintf
. 有更好的方法吗?谢谢
你可以用
vasprintf()
,但这会导致不必要的堆分配—平均速度不太可能更快。使用
alloca
你可以避开堆。或者,你可以直接在
string
返回的是:NRVO应该避免一个拷贝,而C++的11移动语义会把成本SAN-NRVO限制到几个指针交换。
#include
#include
#include
#include
#include
std::string stringf(const char* format, ...)
{
va_list arg_list;
va_start(arg_list, format);
// SUSv2 version doesn't work for buf NULL/size 0, so try printing
// into a small buffer that avoids the double-rendering and alloca path too...
char short_buf[256];
const size_t needed = vsnprintf(short_buf, sizeof short_buf,
format, arg_list) + 1;
if (needed <= sizeof short_buf)
return short_buf;
// need more space...
// OPTION 1
std::string result(needed, ' ');
vsnprintf(result.data(), needed, format, arg_list);
return result; // RVO ensures this is cheap
OR
// OPTION 2
char* p = static_cast(alloca(needed)); // on stack
vsnprintf(p, needed, format, arg_list);
return p; // text copied into returned string
}
int main()
{
std::string s = stringf("test '%s', n %8.2f\n", "hello world", 3.14);
std::cout << s;
}
一个更简单、最初更快的选择是:
std::string result(255, ' '); // 255 spaces + NUL
const size_t needed = vsnprintf(result.data(), result.size() + 1,
format, arg_list);
result.resize(needed); // may truncate, leave or extend...
if (needed > 255) // needed doesn't count NUL
vsnprintf(result.data(), needed + 1, format, arg_list);
return result;
潜在的问题是,您至少分配了256个字符,但实际存储的文本较短:这可能会增加内存/缓存相关性能的开销。你也许可以利用[
shrink_to_fit
]
http://en.cppreference.com/w/cpp/string/basic_string/shrink_to_fit
),但标准并不要求它实际执行任何操作(这些要求是“无约束力的”)。如果您最终不得不复制到一个新的精确大小的字符串,那么您可能已经使用了本地char数组。