我不是C ++开发人员,我想弄清楚为什么当我从一个函数返回一个C字符串时,我会把垃圾拿出来。
#include <stdio.h>
const char* tinker(const char* foo);
int main(void)
{
const char* foo = "foo";
foo= tinker(foo);
printf(foo); // Prints garbage
return 0;
}
const char* tinker(const char* foo)
{
std::string bar(foo);
printf(bar.c_str()); // Prints correctly
return bar.c_str();
}
答案 0 :(得分:8)
您将返回一个基于std::string
内部内存的C字符串。但是,这是在bar
被破坏后打印的。到达printf(foo);
行时,此内存是垃圾。
答案 1 :(得分:4)
您正在返回一个指向bar
内部缓冲区的指针,但是在您使用该指针之前,您正在销毁bar
(和缓冲区)。
如果在函数返回后需要bar
的内容,请返回bar
而不是bar.c_str()
。
答案 2 :(得分:2)
要添加其他人所说的,这是让它发挥作用的一种方法:
#include <stdio.h>
std::string tinker(const char* foo);
int main(void)
{
const char* foo = "foo";
std::string foo2= tinker(foo);
printf(foo2.c_str()); // Prints correctly
return 0;
}
std::string tinker(const char* foo)
{
std::string bar(foo);
return bar;
}
这里std :: string对象通过返回值复制*,然后在main()中打印副本。
*流行的字符串实现采用像引用计数这样的优化来避免实际复制字符串。此外,在C ++ 0x中,字符串对象将被移动,而不是被复制。
答案 3 :(得分:1)
因为你正在修补堆栈中分配bar。当修补程序结束时,它的堆栈被回收,bar被删除,所以你返回的指针指向释放的内存,即退出函数时它不再有效。
答案 4 :(得分:1)
return bar.c_str();
此行返回临时对象的char*
,该函数在函数末尾被删除,因此main()foo
指向已删除的对象char*
。 / p>
答案 5 :(得分:1)
因为酒吧生活在小叮当堆上;离开函数后,它的c_str()就消失了。