奇怪的const char*行为

3
GetTypeName是std::string类型,下面是相关代码。
printf("%#x\n", proto->GetTypeName().c_str());
printf("%s\n", proto->GetTypeName().c_str());
const char *res = proto->GetTypeName().c_str();
printf("%#x\n",res);
printf("%s\n",res);

生成以下输出:

0x90ef78
ValidTypeName
0x90ef78
ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■ю■←ЬЬQщZ

地址始终保持不变;以下代码(行是交换)
const char *res = proto->GetTypeName().c_str();
printf("%#x\n",res);
printf("%s\n",res);
printf("%#x\n", proto->GetTypeName().c_str());
printf("%s\n", proto->GetTypeName().c_str());

运行此代码将产生以下输出,其中地址始终不同:

0x57ef78
  Y
0x580850
ValidTypeName

我做错了什么?
strlen(res)

返回无效的大小,所以我甚至无法使用strcpy函数。

1个回答

5
你的 GetTypeName 函数返回一个 std::string,你调用 c_str 获取该字符串内部数据的指针。由于这是一个临时对象,在语句结束时该 std::string 将被删除。
const char *res = proto->GetTypeName().c_str();

但是您仍然有一个指向已删除数据的res。

编辑:将您的代码更改为以下内容:-

const std::string& res = proto->GetTypeName(); 

在printf中使用如下代码将字符串转换为const char*类型:.c_str()
printf("%#x\n",res.c_str());
printf("%s\n",res.c_str());

将临时变量分配给引用会延长该临时变量的生命周期,使其与引用的生命周期相同...

更好的方法是,只需使用std::string和iostream进行打印,并在不必要时停止使用低级指针 :)


1
@amaurea: 可能是这样,但它有一个缺点:https://dev59.com/d3VC5IYBdhLWcg3w9GLM#134777 - Fred Foo
使用移动语义,为什么不直接将返回的字符串存储在实际字符串中呢?这样查看代码的人就不必知道 GetTypeName 的签名来验证字符串的生命周期了... - Yakk - Adam Nevraumont

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接