文字列 (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
    }
}