我尝试编写一个将值格式化为字符串的函数。但是,我遇到了它的持久性问题。
using namespace std;
string string_format(const string &msg, ...)
{
va_list ap;
char text[BUFF_SIZE] = { 0, };
va_start(ap, msg);
vsnprintf(text, BUFF_SIZE - 1, msg.c_str(), ap);
text[BUFF_SIZE - 1] = '\0';
va_end(ap);
return string(text);
}
int main()
{
char* p1 = (char*)string_format("%d", 123).c_str();
char* p2 = (char*)string_format("%d", 45).c_str();
printf("value: p1=%s, p2=%s\r\n", p1, p2);
}
以上将打印:
值:p1 = 45,p2 = 45
而不是
值:p1 = 123,p2 = 45
我以这种方式编写代码,因为我想同时保留2个或更多char *实例。返回“new string(text)”有效,但我不想继续写“删除”
答案 0 :(得分:2)
当您使用c_str()
时,您将获得指向字符串中内部缓冲区的指针。只要字符串对象仍然存在,该指针才有效。您正在获取指向即时删除的临时字符串对象的指针,这会导致错误的行为。它表现为"持久性"可能是因为两个非常相似的字符串碰巧使用相同的内存空间。在任何情况下,在销毁字符串之后访问指针是未定义的行为。
如果您想使用c_str
,则需要将生成的字符串存储到正确的string
变量中,并在需要指针时将其保留在那里。
或者甚至更好,根本不处理char *
。由于您正在使用C ++,因此请始终为字符串使用正确的字符串对象。
答案 1 :(得分:2)
将结果存储在string
中,并在需要时使用.c_str()
。
string p1 = string_format("%d", 123);
string p2 = string_format("%d", 45);
printf("value: p1=%s, p2=%s\r\n", p1.c_str(), p2.c_str());
答案 2 :(得分:0)
感谢快速而明确的回复。为了实现我的原始目标(使我的代码更具可读性,因为这种缓冲区赋值在我编写的模块中很常见),我最终使用了一个声明字符串作为临时占位符的宏。这次它显示正确的结果
#define ASSIGN_BUFFER(var, format, value) \
string str_##var = string_format(format, value) \
var = (char*)str_##var.c_val()
string string_format(const string &msg, ...)
{
va_list ap;
char text[BUFF_SIZE] = { 0, };
va_start(ap, msg);
vsnprintf(text, BUFF_SIZE - 1, msg.c_str(), ap);
text[BUFF_SIZE - 1] = '\0';
va_end(ap);
return string(text);
}
int main()
{
char *p1, *p2;
ASSIGN_BUFFER(p1, "%d", 123);
ASSIGN_BUFFER(p2, "%d", 45);
printf("value: p1=%s, p2=%s\r\n", p1, p2);
}