Строки (C++/CX)
Текст в среда выполнения Windows представлен в C++/CX классом Platform::String. Platform::String Class
Используйте при передаче строк обратно и обратно в методы в классах среда выполнения Windows или при взаимодействии с другими компонентами среда выполнения Windows через границу двоичного интерфейса приложения (ABI). Platform::String Class
предоставляет методы для некоторых типичных операций над строками, но он является полнофункциональным классом строки. При разработке модуля в C++ используйте стандартные строковые типы C++ (такие как wstring ) для сложной обработки строк и преобразуйте конечный результат в тип Platform::String^ , прежде чем передать его открытому интерфейсу или получить его из такого интерфейса. Операция преобразования между типом wstring
или wchar_t*
и типом Platform::String
проста и эффективна.
Быстрая передача
В некоторых случаях компилятор может удостовериться, что есть возможность безопасно создать экземпляр класса Platform::String
или передать объект String
функции, не копируя основные данные строки. Эти операции называются быстрой передачей , и их выполнение прозрачно.
Создание строк
Значение объекта String
— неизменяемая (доступная только для чтения) последовательность символов char16
(16-разрядных символов Юникода). Поскольку объект String
является неизменяемым, присвоение нового строкового литерала переменной String
фактически заменяет исходный объект String
новым объектом String
. При операции объединения исходный объект String
разрушается, и создается новый объект.
Литералы
Символ-литерал — это символ, заключенный в одиночные кавычки, а строка-литерал — это последовательность символов, заключенная в двойные кавычки. Если для инициализации переменной String^ используется литерал, компилятор предполагает, что литерал состоит из символов char16
. Таким образом, нет необходимости указывать перед литералом модификатор строки "L" или заключать литерал в макрос _T() или TEXT() . Дополнительные сведения о поддержке Юникода в C++ см. в разделах 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::D ata для извлечения текста в виде 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 внутри строк
Строка::Length возвращает количество символов в строке, а не число байтов. Символ NULL, означающий конец строки, не учитывается, если вы не указали обратное при создании строки с помощью семантики стека.
Объект Platform::String
может содержать значения NULL внутри строки, но только если они получены в результате операции объединения. Значения NULL внутри строки не поддерживаются в строковых литералах, поэтому из нельзя использовать для инициализации объектов Platform::String
таким способом. Значения NULL в объектах Platform::String
игнорируются при отображении строки, например когда она присваивается свойству TextBlock::Text
. Когда строковое значение возвращается свойством Data
, значения NULL внутри строки удаляются.
StringReference
В некоторых случаях код (a) получает std::wstring или wchar_t строковый литерал или L", и просто передает его другому методу, который принимает String^ в качестве входного параметра. Если исходный строковый буфер остается допустимым и не изменяется до возвращения результата функцией, строку wchar_t*
или строковый литерал можно преобразовать в Platform::StringReference, а затем передать вместо Platform::String^
. Это допустимо, поскольку в StringReference
имеется определенное пользователем преобразование в тип Platform::String^
. Благодаря StringReference
можно избежать создания дополнительной копии строковых данных. В циклах, включающих передачу большого количества строк или передачу очень длинных строк, с помощью StringReference
можно теоретически добиться значительного выигрыша в производительности. Но поскольку StringReference
фактически занимает исходный строковый буфер, необходимо соблюдать осторожность, чтобы не повредить память. Не следует передавать StringReference
в асинхронный метод, если нет гарантии, что исходная строка будет находиться в области видимости, когда выполнение метода закончится. При инициализации String^ из StringReference происходит принудительное выделение памяти и копирование содержимого строки, если имеется второй оператор присваивания. В этом случае выигрыш в производительности StringReference
теряется.
Обратите внимание, что StringReference
является типом класса стандартного языка C++, а не ссылочным классом; его нельзя использовать в определяемых пользователем открытых интерфейсах ссылочных классов.
В следующем примере показано, как использовать 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
}
}