一個選項是臨時緩衝區啓動一些已知的大小,然後增加它,如果看到它不夠用vsnprintf
。有更好的方法嗎?謝謝
您可以使用vasprintf()
,但這不需要堆分配 - 它不可能平均更快。使用alloca
可以避免堆。或者,您可以直接寫入返回的string
:NRVO應該避免複製,並且從C++ 11開始,移動語義會將成本sans-NRVO限制爲少數指針交換。
#include <cstdio>
#include <cstdarg>
#include <alloca.h>
#include <string>
#include <iostream>
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<char*>(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)的問題,但該標準並不要求它實際上做任何事情(的要求是「非綁定」)。如果最終不得不復制到一個新的精確大小的字符串,那麼最好使用本地字符數組。
爲了方便使用,請考慮使用諸如Boost.Format之類的東西。變量函數不是類型安全的,不能用於非POD類型。 Boost.Format非常易於使用,是類型安全的,可以安全地用於任何類型。 – 2010-11-15 06:56:47
@詹姆斯,謝謝,但我正在尋找答案沒有提升 – zaharpopov 2010-11-15 07:10:33
你看過Boost.Format的來源?它可能會給你一些提示(但也可能需要一些時間來理解)。 – 2010-11-15 07:43:35