4

我是一个 C/C++ 初学者,试图构建一个看起来非常简单的程序:它将文件加载到 c 字符串 (const char*) 中。然而,虽然这个程序非常简单,但它并没有以我理解的方式工作。看一看:

#include <iostream>
#include <fstream>

std::string loadStringFromFile(const char* file)
{
    std::ifstream shader_file(file, std::ifstream::in);
    std::string str((std::istreambuf_iterator<char>(shader_file)), std::istreambuf_iterator<char>());
    return str;
}

const char* loadCStringFromFile(const char* file)
{
    std::ifstream shader_file(file, std::ifstream::in);
    std::string str((std::istreambuf_iterator<char>(shader_file)), std::istreambuf_iterator<char>());
    return str.c_str();
}

int main()
{
    std::string hello = loadStringFromFile("hello.txt");
    std::cout << "hello: " << hello.c_str() << std::endl;

    const char* hello2 = loadCStringFromFile("hello.txt");
    std::cout << "hello2: " << hello2 << std::endl;

    hello2 = hello.c_str();
    std::cout << "hello2 = hello.c_str(), hello2: " << hello2 << std::endl;

    return 0;
}

输出如下所示:

hello: Heeeeyyyyyy

hello2:       青!
hello2 = hello, hello2: Heeeeyyyyyy

初始的 hello2 值每次都会改变,总是一些随机的汉字(我使用的是日本电脑,所以我猜这就是为什么它是汉字)。

在我天真的观点中,这两个值似乎应该打印相同。一个函数返回一个 c++ 字符串,然后我将其转换为 c 字符串,另一个函数加载该字符串,从该字符串转换 c 字符串并返回它。我通过在返回它之前计算值来确保字符串在 loadCStringFromFile 中正确加载,确实这是我的想法,例如:

/*(inside loadCStringFromFile)*/
const char* result = str.c_str();
std::cout << result << std::endl;//prints out "Heeeyyyyyy" as expected
return result;

那么为什么要改变价值呢?谢谢您的帮助...

4

3 回答 3

4

您的问题是strinloadCStringFromFile是一个局部变量,并且在函数返回时被破坏。那时的返回值c_str()是无效的。

更多细节在这里

您的第一个函数loadStringFromFile是一种更类似于 C++ 的方式,并说明了让类为您管理内存的好处。如果您使用 char*,那么您必须更加小心分配和释放内存的位置。

于 2012-08-05T10:17:20.643 回答
3

功能

std::string loadStringFromFile(const char* file)

返回在函数内部创建的字符串的字符串副本,该副本在字符串超出范围之前被复制,即函数结束,这就是它起作用的原因。

const char* loadCStringFromFile(const char* file)

另一方面,返回一个指向本地字符串的指针,该指针在函数返回时超出范围并被销毁,因此返回的地址 theconst char*指向未定义的某个位置。

为了使第二种方法起作用,您需要在调用函数之前创建字符串:

const char* loadCStringFromFile(const char* file, string& str); // return str.c_str()

..
string str;
const char* result = loadCStringFromFile(file,str);

或者您在函数的堆上创建一个字符串并将地址传回,但这会有点混乱,因为调用者需要删除字符串以避免memleak。

于 2012-08-05T10:36:28.900 回答
-1

您应该复制 str.c_str() 的输出:

return strdup(str.c_str);

函数strdup可以在 cstring 标头中找到。

于 2012-08-05T10:17:44.887 回答