4

私は非常に単純なプログラムのように見えるものを構築しようとしている C/C++ の初心者です。ファイルを c-string (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 の初期値は毎回変化し、常にランダムな漢字です (私は日本語のコンピューターを使用しているので、それが漢字であると推測しています)。

私の素朴な見解では、2 つの値が同じように出力されるはずです。1 つの関数は c++ 文字列を返し、それを c-string に変換し、もう 1 つの関数は文字列を読み込み、そこから c-string を変換して返します。値を返す前に値を計算することで、文字列が 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)

一方、関数が返されて破棄されるとスコープ外になるローカル文字列へのポインターを返すため、返されたアドレス はconst char*未定義の場所を指します。

2 番目の方法を機能させるには、関数を呼び出す前に文字列を作成する必要があります。

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

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

または、関数のヒープに文字列を作成してアドレスを返しますが、メモリリークを避けるために呼び出し元が文字列を削除する必要があるため、少し面倒です。

于 2012-08-05T10:36:28.900 に答える
-1

str.c_str() の出力を複製する必要があります。

return strdup(str.c_str);

関数strdupは cstring ヘッダーにあります。

于 2012-08-05T10:17:44.887 に答える