文字列 (C++/CX)
Windows ランタイム内のテキストは、Platform::String Class によって C++/CX で表されます。 Windows ランタイムのクラスのメソッド間で文字列を渡すときや、アプリケーション バイナリ インターフェイス (ABI) の境界を越えて他の Windows ランタイムのコンポーネントとやり取りするときは、Platform::String Class
を使用します。 Platform::String Class
は、いくつかの一般的な文字列操作のメソッドを提供しますが、すべての機能を備えた文字列クラスとしては設計されていません。 C++ モジュールでは、重要なテキスト処理のために wstring などの標準 C++ 文字列型を使用し、パブリック インターフェイスとの間でやり取りする前に、最終結果を Platform::String^ に変換します。 wstring
または wchar_t*
と Platform::String
の間で変換することは簡単かつ効率的です。
高速渡し
場合によっては、コンパイラは基になる文字列データをコピーせずに Platform::String
を安全に構築したり、 String
を関数に渡したりできることを確認できます。 このような操作は 高速渡し と呼ばれ、透過的に行われます。
文字列の構築
String
オブジェクトの値は、変更できない (読み取り専用) char16
(16 ビット Unicode) 文字のシーケンスです。 String
オブジェクトは変更できないため、 String
変数に新しい文字列リテラルを代入すると、元の String
オブジェクトが新しい String
オブジェクトで置き換えられます。 連結操作には、元の String
オブジェクトの破棄と新しいオブジェクトの作成が含まれます。
リテラル
リテラル文字 は単一引用符で囲まれた 1 文字で、 リテラル文字列 は二重引用符で囲まれた文字のシーケンスです。 リテラルを使用して String^ 変数を初期化する場合、コンパイラはリテラルが char16
文字で構成されていると仮定します。 つまり、リテラルの前に文字列修飾子 'L' を挿入したり、 _T() または TEXT() マクロでリテラルを囲んだりする必要はありません。 C++ の Unicode サポートの詳細については、「 Unicode Programming Summary」を参照してください。
次の例に、 String
オブジェクトを構築するさまざまな方法を示します。
// Initializing a String^ by using string literals
String^ str1 = "Test"; // ok for ANSI text only. uses current code page
String^ str2("Test");
String^ str3 = L"Test";
String^ str4(L"Test");
//Initialize a String^ by using another String^
String^ str6(str1);
auto str7 = str2;
// Initialize a String from wchar_t* and wstring
wchar_t msg[] = L"Test";
String^ str8 = ref new String(msg);
std::wstring wstr1(L"Test");
String^ str9 = ref new String(wstr1.c_str());
String^ str10 = ref new String(wstr1.c_str(), wstr1.length());
文字列処理の操作
String
クラスは、文字列連結、文字列比較、その他の基本的な文字列操作のメソッドを提供します。 より広範囲の文字列操作を実行するには、 String::Data()
メンバー関数を使用して、 String^
として const wchar_t*
オブジェクトの値を取得します。 そして、その値を使用して、豊富な文字列処理を提供する std::wstring
を初期化します。
// Concatenation
auto str1 = "Hello" + " World";
auto str2 = str1 + " from C++/CX!";
auto str3 = String::Concat(str2, " and the String class");
// Comparison
if (str1 == str2) { /* ... */ }
if (str1->Equals(str2)) { /* ... */ }
if (str1 != str2) { /* ... */ }
if (str1 < str2 || str1 > str2) { /* ... */};
int result = String::CompareOrdinal(str1, str2);
if(str1 == nullptr) { /* ...*/};
if(str1->IsEmpty()) { /* ...*/};
// Accessing individual characters in a String^
auto it = str1->Begin();
char16 ch = it[0];
文字列変換
Platform::String
には、 char16
文字または NULL
文字だけを含めることができます。 アプリケーションで 8 ビット文字を使用する必要がある場合は、String::Data を使用して、const wchar_t*
としてテキストを抽出します。 そして、適切な Windows 関数または標準ライブラリ関数を使用してデータを操作し、データを wchar_t*
または wstringに戻します。これらを使用して、新しい Platform::String
で表されます。
次のコードに、 String^
変数と wstring
変数の間で変換する方法を示します。 この例で使用される文字列操作の詳細については、「 basic_string::replace」を参照してください。
// Create a String^ variable statically or dynamically from a literal string.
String^ str1 = "AAAAAAAA";
// Use the value of str1 to create the ws1 wstring variable.
std::wstring ws1( str1->Data() );
// The value of ws1 is L"AAAAAAAA".
// Manipulate the wstring value.
std::wstring replacement( L"BBB" );
ws1 = ws1.replace ( 1, 3, replacement );
// The value of ws1 is L"ABBBAAAA".
// Assign the modified wstring back to str1.
str1 = ref new String( ws1.c_str() );
文字列の長さと埋め込み NULL 値
String::Length を指定すると、バイト数ではなく、文字列内の文字数が返されます。 スタック セマンティクスを使用して文字列を構築すると、終端の NULL 文字は明示的に指定しない限りカウントされません。
Platform::String
には埋め込み NULL 値を含めることができますが、連結演算の結果として NULL 値が含まれるときだけです。 埋め込み NULL は文字列リテラルではサポートされないため、 Platform::String
を初期化するためにそのように埋め込まれた NULL は使用できません。 Platform::String
内の埋め込み NULL 値は、文字列が TextBlock::Text
プロパティに割り当てられたときなど、文字列が表示されるときには無視されます。 埋め込み NULL は、文字列値が Data
プロパティによって返されるときに削除されます。
StringReference
特定の状況では、コード (a) は std::wstring、または wchar_t 文字列か L"" リテラル文字列を受け取り、String^ を入力パラメーターとして受け取る別のメソッドにそれを渡します。 元の文字列バッファー自体が有効な状態にとどまり、関数が制御を返す前に変更されていない場合、 wchar_t*
文字列またはリテラル文字列を Platform::StringReferenceに変換し、 Platform::String^
の代わりにそれを渡すことができます。 StringReference
には、 Platform::String^
に対するユーザー定義の変換があるため、この操作が許可されます。 StringReference
を使用して、文字列データの余分なコピーを回避することもできます。 多数の文字列を渡すループの中や、非常に大きな文字列を渡す場合は、 StringReference
を使用すると、パフォーマンスの大幅な向上を実現できる可能性があります。 ただし、 StringReference
は基本的に元の文字列バッファーをそのまま利用するので、メモリの破損を防止するために十分注意する必要があります。 メソッドが制御を返すときに、元の文字列がスコープ内にあることが保証されている場合以外は、非同期メソッドに StringReference
を渡さないでください。 2 番目の代入演算が発生した場合、StringReference によって初期化される String^ で、文字列データの割り当てとコピーが強制的に実行されます。 この場合、 StringReference
が持つパフォーマンスの利点が失われます。
StringReference
は ref クラスではなく、標準 C++ のクラス型であるため、定義した ref クラスのパブリック インターフェイス内で使用できないことに注意してください。
StringReference を使用する方法を次のコード例に示します。
void GetDecodedStrings(std::vector<std::wstring> strings)
{
using namespace Windows::Security::Cryptography;
using namespace Windows::Storage::Streams;
for (auto&& s : strings)
{
// Method signature is IBuffer^ CryptographicBuffer::DecodeFromBase64String (Platform::String^)
// Call using StringReference:
IBuffer^ buffer = CryptographicBuffer::DecodeFromBase64String(StringReference(s.c_str()));
//...do something with buffer
}
}