将(文件读取)函数返回值转换为c_str()的行为不符合预期

时间:2015-11-26 03:54:23

标签: c++ string

我有一个读取文件并返回字符串的函数。

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是空的。任何见解都表示赞赏。

3 个答案:

答案 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()的调用返回指向其内部内容的指针,但随后字符串被销毁,导致返回无效。