3


2

.c_str()奇妙さ? 韻や理由なくデータが変化しますか?

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

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 *があります。 ただし、戻ると、データはガベージデータに切り替わります。 間に機能はありません。 何ができる?

5 Answer


11


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

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


5


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


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`クラスによって管理される文字列がメモリ内で再配置されることはないと想定しているため、これは依然として危険です。 たとえば、 `StringManager`が std

vector`の助けを借りて実装されている場合、ベクターを展開する必要があるとすぐに、以前のコンテンツがより大きなメモリブロックの別の場所にコピーされ、最終的にもう存在しないオブジェクト。

つまり、http://www.gotw.ca/gotw/070.htm [内部データへのハンドルを返すことを避けてください]。


1


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


0


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