3

私はこの単純な機能を持っています:

const wchar_t *StringManager::GetWCharTStar(int stringId)
{
    std::wstring originalString = StringManager::GetString(stringId);
    const wchar_t *retStr = originalString.c_str();
    return retStr;
}

その関数の 2 行目に、正しい wchar_t* があります。しかし、私が戻ってくると、データはガベージデータに切り替わります。間に機能はありません。何が得られる?!

4

5 に答える 5

11

originalString はスタックに割り当てられます。.c_str() メソッドは、wstring オブジェクトの連続した内部メモリへのポインターを返すだけです。関数が戻ると、 originalString はスコープ外になり破棄されるため、返されるポインター値は削除されたメモリを指します。

これを行う必要がある場合は、new または malloc() で割り当てたメモリにデータのコピーを作成し、呼び出し元がそのメモリを削除/解放する必要があります。

于 2009-12-07T17:38:51.703 に答える
5

一時へのポインターを返しています。originalString が範囲外になると、ポインターが指しているデータは削除されます。

于 2009-12-07T17:38:56.330 に答える
3

std::wstring originalString;関数の本体内のローカル変数ですGetWCharTStar

関数のスコープを離れるとすぐにGetWCharTStar()、このローカル変数は破棄され、返されるポインターは無効になります。

次のコードは最終的に機能する可能性があります。

const wchar_t *StringManager::GetWCharTStar(int stringId)
{
    const std::wstring& originalString = StringManager::GetString(stringId);
    const wchar_t *retStr = originalString.c_str();
    return retStr;
}

参照StringManager::GetString()を返します:

const std::wstring& StringManager::GetString(int stringId);

StringManagerただし、クラスによって管理される文字列がメモリ内で再配置されることはないと想定しているため、これは依然として危険です。たとえば、ベクトルを拡張する必要があるとすぐに thenStringManagerを使用して が実装されている場合std::vector、以前の内容がより大きなメモリ ブロックの別の場所にコピーされ、存在しないオブジェクトへの参照を保持することになります。

つまり、内部データへのハンドルを返さないようにします

于 2009-12-07T17:39:43.817 に答える
1

以前の回答は、1 つの小さな詳細を除いて、ほとんど正しいです。破棄されたオブジェクトへのポインターを返すのではなく、破棄されたオブジェクトが所有するポインターを返します。そのオブジェクトが破棄されたとき、ポインターが指していたオブジェクトも破棄されました。

于 2009-12-07T17:42:56.197 に答える
0

これはよくある質問です。実際に使用する前に、解放されたオブジェクト (originalString オブジェクト) へのポインターを返しています。

于 2009-12-07T17:39:23.987 に答える