我有一个返回字符串的函数。但是,当我调用它并对其执行c_str()以将其转换为const char *时,它仅在我首先将其存储到另一个字符串时才起作用。如果我直接从函数中调用c_str(),它会将垃圾值存储在const char *中。
为什么会这样?感觉我在这里缺少一些非常基本的东西......
string str = SomeFunction();
const char* strConverted = str.c_str(); // strConverted stores the value of the string properly
const char* charArray= SomeFunction().c_str(); // charArray stores garbage value
static string SomeFunction()
{
string str;
// does some string stuff
return str;
}
答案 0 :(得分:19)
SomeFunction().c_str()
为您提供指向临时(str
正文中的自动变量SomeFunction
)的指针。与引用不同,在这种情况下,临时工的生命周期不会延长,最终charArray
是一个悬空指针,解释了当您尝试使用charArray
时稍后看到的垃圾值。
另一方面,当你做
时string str_copy = SomeFunction();
str_copy
是SomeFunction()
的返回值的副本。现在调用c_str()
会为您提供指向有效数据的指针。
答案 1 :(得分:2)
函数返回的值对象是临时的。 c_str()
的结果仅在临时的生命周期内有效。在大多数情况下,临时的生命周期是完整表达式的结尾,通常是分号。
const char *p = SomeFunction();
printf("%s\n", p); // p points to invalid memory here.
解决方法是确保在完整表达式结束之前使用c_str()
的结果。
#include <cstring>
char *strdup(const char *src_str) noexcept {
char *new_str = new char[std::strlen(src_str) + 1];
std::strcpy(new_str, src_str);
return new_str;
}
const char *p = strdup(SomeFunction.c_str());
请注意,strdup
是POSIX函数,因此如果您是支持POSIX的平台,那么它已经存在。
答案 2 :(得分:0)
方法string str
中的“SomeFunction()
”是SomeFunction()
中的局部变量,只能在SomeFunction()
范围内生存;
由于方法SomeFunction()
的返回类型是字符串,而不是字符串的引用,在“return str;
”之后,SomeFunction()
将返回值{的副本{1}},在str
调用后,将作为临时值存储在某个内存位置,临时值将立即销毁;
“SomeFunction()
”会将返回的临时值string str = SomeFunction();
存储到字符串SomeFunction()
,实际上是该值的副本并存储到str
,在“str
”str
的调用完成后,SomeFunction()
的生命周期大于;
的生命周期,并且返回的临时值会立即销毁,内存将由系统回收,但此值的副本仍存储在SomeFunction()
中。这就是为什么“str
”可以获得正确的值,实际上const char* strConverted = str.c_str();
返回了c_str()
的初始元素的指针(str
的第一个元素内存地址指向的字符串值),而不是返回的临时值str
;
“SomeFunction()
”不同,“const char* charArray= SomeFunction().c_str();
”将返回返回临时值的初始元素的指针(返回的临时字符串值的第一个元素内存地址),但是在调用SomeFunction().c_str()
之后,返回的临时值被销毁,并且系统重用该内存地址,SomeFunction()
可以获取该内存地址的值,但不能获得您期望的值;
答案 3 :(得分:-3)
使用strcpy将字符串复制到本地定义的数组,您的代码将正常工作。