【问题标题】:converting (file reading) function return value to c_str() not behaving as expected将(文件读取)函数返回值转换为 c_str() 的行为不符合预期
【发布时间】:2015-11-26 12:51:16
【问题描述】:

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

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

【问题讨论】:

    标签: c++ string


    【解决方案1】:

    您的函数调用返回的字符串在这两种情况下都是临时的。对该临时对象调用 c_str() 会返回一个指针,该指针可能在语句完成后悬空。使用字符串存储结果是正确的,这就是第一次调用有效的原因。由于悬空指针,第二次调用可能会产生不良影响。

    由于str2 是一个指针,它不仅仅是空的,它指向一个不存在的字符串。这可能是一种危险。

    将结果存储到另一个字符串中,就像在第一次调用中一样,编译器可能会很好地优化。

    您也可以缩短读取的文件:

    ...
    ifstream in(filename);
    if (in)
    {
        return string(istreambuf_iterator<char>(in), istreambuf_iterator<char>());
    }
    
    // throw exception
    ...
    

    【讨论】:

    【解决方案2】:

    使用str1,您将其设置为局部变量str 的内部,该变量在函数末尾超出范围之前一直有效(只要您不修改str)。

    使用str2,您将它指向一个从未分配给局部变量的临时字符串的内部,因此它在您分配后立即被销毁。

    【讨论】:

      【解决方案3】:

      问题在于c_str() 返回的指针仅在其获取的字符串未被修改或处置时才有效。

      当你这样做时

      const char* str2 = get_file_contents("test.txt").c_str();
      

      get_file_contents("test.txt") 返回的字符串是临时的。对c_str() 的调用返回一个指向其内部内容的指针,但随后该字符串被破坏,导致返回无效。

      【讨论】:

      • 建议的解决方案可行,但更丑陋。你也误解了这个问题。
      猜你喜欢
      • 2017-10-31
      • 1970-01-01
      • 2019-02-07
      • 1970-01-01
      • 2022-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多