CStringをstd::stringに変換

マルチバイト環境での変換の話です。

例1

表題の変換について調べると以下のような例がよく紹介されています。

    CString sample1 = _T("テスト");
    std::string sample2 = sample1.GetBuffer();

GetBuffer()でLPTSTR型(TCHAR*)のポインタを取得して代入している形です。この場合、このポインタを使用して文字列の内容を変更していないのでReleaseBuffer()は不要です。

例2

例1の変換は文字列の内容を変更しないため、変更可能なLPTSTR型を使用する必要はありません。したがって、以下のようにLPCTSTR型(const TCHAR*)に変換し、コンストラクタの引数にする方法もよく紹介されています。

    CString sample1 = _T("テスト")
    std::string sample2((LPCTSTR)sample1);

今変換するなら?

さて、例2のキャスト変換ですが実はstd::stringに変換する場合必要ありません。
CStringはCStringTのテンプレートパラメータにTCHAR型を指定したテンプレートクラスの別名です。CStringTはCSimpleStringTを継承しています。CSimpleStringTでは以下の演算子のオーバーロードが定義されています。これが働き暗黙的な型変換がおこなわれるためです。PCXSTR型はマルチバイト環境の場合LPCSTR型の別名です。LPCTSTR型もマルチバイト環境ではLPCSTR型の別名ですね。

operator PCXSTR() const throw();

https://learn.microsoft.com/ja-jp/cpp/atl-mfc-shared/reference/csimplestringt-class?view=msvc-160#operator_pcxstr

結局のところ以下で問題ないということです。

    CString sample1 = _T("テスト")
    std::string sample2(sample1);

ただし、CStringT::Formatのような可変個引数の場合はキャストが必要になります。詳細はMSDNで説明されています。

まとめ

なんでこんなことを今更調べなおしたかというと、GetBuffer()を使用したとき、セットでReleaseBuffer()を使用しないとメモリーリークすると目に入ったからです。

ネット上に存在するのが10~20年ぐらい前の情報ばかりなのでしょうがないのですが、混乱が起きそうなので例1はリファクタリングしていこうと思います。

参考

https://stackoverflow.com/questions/559483/cstring-to-char

https://stackoverflow.com/questions/24482869/how-to-convert-cstring-to-tchar-in-c/24483032#24483032

https://stackoverflow.com/questions/258050/how-do-you-convert-cstring-and-stdstring-stdwstring-to-each-other

https://rarara.org/community/programming/LPCTSTR%E3%81%B8%E3%81%AE%E3%82%AD%E3%83%A3%E3%82%B9%E3%83%88/

タイトルとURLをコピーしました