1

私にはstd::wstring decode(const char *s)機能があります。

私はこのように使用します:

const char *src = "some string";
const wchar_t *result = decode(src).c_str();

私はいつも にゴミがresult[0]入りresult[1]ます。

別の方法で使用すると、ゴミが発生しません。

std::wstring res = decode(src);
const wchar_t *result = res.c_str();

以下のように定義された私のdecode関数は、それが仕事です。唯一の問題は、コードを呼び出すことです(上記)。

std::wstring decode(const char *s, UINT cp=CP_ACP)
{
    if(s == NULL)
        return std::wstring();
    int length = ::MultiByteToWideChar(cp, 0, s, -1, NULL, 0 );
    wchar_t *buf = new wchar_t[length];
    ::MultiByteToWideChar(cp, 0, s, -1, buf, length);
    std::wstring r(buf);
    delete[] buf;
    return r;
}

Visual C++ 2008 SP1 を使用してコンパイルします。

4

3 に答える 3

7
const wchar_t *result = decode(src).c_str();

の戻り値decodeは一時的な値であり、 の呼び出し後に破棄されc_str()ます。したがってresult、解放されたメモリを指します。

だからどちらか

  • 戻り値の有効期間を延長します (たとえば、ローカル変数に割り当てます)。
  • 結果をコピーする
于 2014-10-10T16:53:21.847 に答える
5

12.2 一時オブジェクト[class.temporary]

3 実装が自明でないコンストラクタ (12.1、12.8) を持つクラスの一時オブジェクトを導入する場合、一時オブジェクトに対してコンストラクタが呼び出されることを保証する必要があります。同様に、非自明なデストラクタ (12.4) を使用して一時的にデストラクタを呼び出す必要があります。一時オブジェクトは、それらが作成されたポイントを (レキシカルに) 含む完全な式 (1.9) を評価する最後のステップとして破棄されます。これは、その評価が例外のスローで終了した場合でも当てはまります。値の計算と一時オブジェクトの破棄の副作用は、特定の部分式ではなく、完全な式にのみ関連付けられます。

したがって、最初の例のように、破棄された後に一時的なものを使用しないでください。

于 2014-10-10T16:52:43.510 に答える
1

特定の問題に対する答えは、提供されている両方の良い答えにあります。質問のタイトルは単にだったので、関数なしwstring::c_str() contains garbageで正しい結果を得る方法を指摘します。decode

Microsoft は、ワイド文字 (Unicode) と MBCS (Ascii) の間で変換するための多数のATL変換マクロとクラスを追加しました。それらは VS2008 で利用できます。サポートされている変換は、 MSDN ドキュメントで見つけることができます。

ATL 7.0 では、いくつかの新しい変換クラスとマクロが導入され、既存のマクロが大幅に改善されています。新しい文字列変換クラスとマクロの名前は、 C SourceType 2 [C]DestinationType[EX] の形式を取ります。

[をちょきちょきと切る]

SourceType/DestinationType

A = ANSI 文字列。

W = Unicode 文字列。

T = 汎用文字列 (_UNICODE が定義されている場合は W と同等、そうでない場合は A と同等)。

OLE = OLE 文字列 (W に相当)。

これ[EX]はオプションであり、マクロで使用されるデフォルトの内部バッファーのサイズを指定したくない場合によく使用されます。

あなたの場合、変換マクロCA2W(AsciiをWidecharに変換する)はあなたが望むことをするはずです。#include <atlbase.h>それらを使用するだけです。これらのマクロは、変換する文字列とコード ページの 2 つのパラメータを受け取ります (指定されていない場合、デフォルトは CP_ACP になります)。

あなたの場合、あなたは持っていました:

std::wstring res = decode(src);
const wchar_t *result = res.c_str();

ATL 変換マクロを使用すると、次のように実行できます。

std::wstring res = CA2W(src, CP_ACP);
const wchar_t *result = res.c_str();

マクロのデフォルトは Ansi Code Page であるため、次のように CP_ACP をオフにすることもできます。

std::wstring res = CA2W(src);
const wchar_t *result = res.c_str();

一時オブジェクトの問題に関しては、これらのマクロによって返されるクラスにも同じことが当てはまります。Microsoft は、以前に提供されたリンクで、この問題を誤った使用例で文書化しています。

// Example 3 
// Incorrect use of conversion macros. 
void ExampleFunction3(LPCWSTR pszW)
{
    // Create a temporary instance of CW2A, 
    // save a pointer to it and then delete 
    // the temportary instance.
    LPCSTR pszA = CW2A(pszW);
    // The pszA in the following line is an invalid pointer, 
    // as the instance of CW2A has gone out of scope.
   ExampleFunctionA(pszA);
}
于 2014-10-10T18:14:22.913 に答える