我有一个读取文件并返回字符串的函数。
string get_file_contents(const char *filename)
{
ifstream in(filename);
if (in)
{
ostringstream contents;
contents << in.rdbuf();
in.close();
return(contents.str());
}
throw(errno);
}
我读了一个只包含success
的文件,并以两种不同的方式将返回值转换为c
样式字符串,结果不同。
string str = get_file_contents("test.txt");
const char* str1 = str.c_str();
cout << "printing str1: ";
cout << str1 << endl;
const char* str2 = get_file_contents("test.txt").c_str();
cout << "printing str2: ";
cout << str2 << endl;
输出:
printing str1: success
printing str2:
我不明白为什么str2是空的。任何见解都表示赞赏。
答案 0 :(得分:3)
使用str1
,您将其设置为局部变量str
的内部,该变量在函数结束时超出范围之前保持有效(只要您不要这样做)修改str
)。
使用str2
,您将其指向临时字符串的内部,该字符串从未分配给本地变量,因此在您分配后立即销毁它。
答案 1 :(得分:3)
您的函数调用返回一个在两种情况下都是临时的字符串。在该临时文件上调用c_str()
会返回一个指针,该指针可能在语句完成后悬空。使用字符串存储结果是正确的,这就是第一次调用有效的原因。由于悬空指针,第二次调用可能会产生不良影响。
由于str2
是一个指针,它不仅仅是空的,而是指向一个不存在的字符串。这可能是一种危险。
将结果存储到另一个字符串中,就像在第一次调用中一样,编译器可以很好地优化它。
您也可以缩短读取的文件:
...
ifstream in(filename);
if (in)
{
return string(istreambuf_iterator<char>(in), istreambuf_iterator<char>());
}
// throw exception
...
答案 2 :(得分:2)
问题是c_str()
返回的指针只有在没有修改或处理获取它的字符串时才会保持有效。
当你这样做时
const char* str2 = get_file_contents("test.txt").c_str();
get_file_contents("test.txt")
返回的字符串是临时的。对c_str()
的调用返回指向其内部内容的指针,但随后字符串被销毁,导致返回无效。