Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В программе C++/CX можно бесплатно использовать контейнеры стандартной библиотеки шаблонов (STL) или любой другой определяемый пользователем тип коллекции. Однако при передаче коллекций между среда выполнения Windows двоичным интерфейсом приложения (ABI), например в элемент управления XAML или клиенту JavaScript, необходимо использовать среда выполнения Windows типы коллекций.
Среда выполнения Windows определяет интерфейсы для коллекций и связанных типов, а C++/CX предоставляет конкретные реализации C++ в файле заголовка collection.h. На этой иллюстрации показаны связи между типами коллекций:
Класс
Platform::Collections::Vector
напоминаетstd::vector
класс.Класс
Platform::Collections::Map
напоминаетstd::map
класс.Platform::Collections::VectorView
класс иPlatform::Collections::MapView
класс — это версииVector
, доступные только для чтения, иMap
.Итераторы определяются в
Platform::Collections
пространстве имен. Эти итераторы удовлетворяют требованиям для итераторов STL и позволяют использоватьstd::find
std::count_if
и другие алгоритмы STL для любогоWindows::Foundation::Collections
типа интерфейса илиPlatform::Collections
конкретного типа. Например, это означает, что можно выполнить итерацию коллекции в компоненте среда выполнения Windows, созданном в C# и применить к нему алгоритм STL.Important
Итераторы прокси-сервера
VectorIterator
иVectorViewIterator
используют прокси-объектыVectorProxy<T>
иArrowProxy<T>
для включения использования с контейнерами STL. Для получения дополнительной информации см. элемент VectorProxy далее в этой статье.Типы коллекций C++/CX поддерживают ту же безопасность потоков, что и контейнеры STL.
Windows::Foundation::Collections::IObservableVector
иWindows::Foundation::Collections::IObservableMap
определяют события, которые запускаются при изменении коллекции различными способами. Реализуя эти интерфейсы,Platform::Collections::Map
иPlatform::Collections::Vector
поддерживают привязку данных с помощью коллекций XAML. Например, если имеется объектVector
, данные которого связаны сGrid
, то при добавлении данных в коллекцию их изменения отражаются в пользовательском интерфейсе таблицы.
Vector usage
Когда класс должен передать контейнер последовательности другому компоненту среды выполнения Windows, используйте Windows::Foundation::Collections::IVector<T>
его в качестве параметра или возвращаемого типа, а Platform::Collections::Vector<T>
также в качестве конкретной реализации. При попытке использования типа Vector
в качестве открытого возвращаемого значения или параметра возникнет ошибка компилятора C3986. Эту ошибку можно исправить, заменив Vector
объектом IVector
.
Important
В случае передачи последовательности внутри разрабатываемой программы используйте Vector
или std::vector
, поскольку они более эффективны по сравнению с IVector
. Используйте IVector
только при передаче контейнера с помощью ABI.
Система типов среда выполнения Windows не поддерживает концепцию сорных массивов, поэтому нельзя передать IVector<Platform::Array<T>>
в качестве возвращаемого значения или параметра метода. Для передачи массива массивов или последовательности массивов в ABI используйте IVector<IVector<T>^>
.
КлассVector<T>
предоставляет методы, необходимые для добавления и удаления элементов коллекции и доступа к ним. Его можно неявно преобразовать в класс IVector<T>
. Алгоритмы STL также можно применять к экземплярам Vector<T>
. В следующем примере демонстрируются некоторые простейшие варианты использования. Функция begin
иend
функция здесь находятся из Platform::Collections
пространства имен, а не std
пространства имен.
#include <collection.h>
#include <algorithm>
using namespace Platform;
using namespace Platform::Collections;
using namespace Windows::Foundation::Collections;
void Class1::Test()
{
Vector<int>^ vec = ref new Vector<int>();
vec->Append(1);
vec->Append(2);
vec->Append(3);
vec->Append(4);
vec->Append(5);
auto it =
std::find(begin(vec), end(vec), 3);
int j = *it; //j = 3
int k = *(it + 1); //or it[1]
// Find a specified value.
unsigned int n;
bool found = vec->IndexOf(4, &n); //n = 3
// Get the value at the specified index.
n = vec->GetAt(4); // n = 3
// Insert an item.
// vec = 0, 1, 2, 3, 4, 5
vec->InsertAt(0, 0);
// Modify an item.
// vec = 0, 1, 2, 12, 4, 5,
vec->SetAt(3, 12);
// Remove an item.
//vec = 1, 2, 12, 4, 5
vec->RemoveAt(0);
// vec = 1, 2, 12, 4
vec->RemoveAtEnd();
// Get a read-only view into the vector.
IVectorView<int>^ view = vec->GetView();
}
Если у вас есть существующий код, который используется std::vector
и вы хотите повторно использовать его в компоненте среда выполнения Windows, просто используйте один из Vector
конструкторов, которые принимают std::vector
или пару итераторов, чтобы создать в Vector
точке, где вы передаете коллекцию через ABI. В следующем примере показано использование конструктора класса Vector
для эффективной инициализации из объекта std::vector
. После операции перемещения исходная переменная vec
более не является допустимой.
//#include <collection.h>
//#include <vector>
//#include <utility> //for std::move
//using namespace Platform::Collections;
//using namespace Windows::Foundation::Collections;
//using namespace std;
IVector<int>^ Class1::GetInts()
{
vector<int> vec;
for(int i = 0; i < 10; i++)
{
vec.push_back(i);
}
// Implicit conversion to IVector
return ref new Vector<int>(std::move(vec));
}
Если имеется вектор строк, которые должны будут передаваться через интерфейс ABI, необходимо решить, следует ли изначально создавать строки как типы std::wstring
или как типы Platform::String^
. Если предполагается выполнение большого объема операций с этими строками, используйте тип wstring
. В противном случае создайте строки типа Platform::String^
, чтобы избежать издержек, связанных с их последующим преобразованием. Кроме того, необходимо определить, куда лучше поместить строки для внутреннего использования — в std::vector
или в Platform::Collections::Vector
. В общем случае рекомендуется использовать объект std::vector
и создавать из него Platform::Vector
только при передаче контейнера через интерфейс ABI.
Типы значений в объекте Vector
Любой элемент, хранящийся в объекте Platform::Collections::Vector
, должен поддерживать сравнение равенства либо неявно, либо с помощью предоставленного пользовательского std::equal_to
компаратора. Все ссылочные типы и все скалярные типы неявно поддерживают сравнение на равенство. Для не скалярных типов значений, таких как Windows::Foundation::DateTime
, или для пользовательских сравнений, например objA->UniqueID == objB->UniqueID
, необходимо предоставить пользовательский объект функции.
VectorProxy elements
Platform::Collections::VectorIterator
и Platform::Collections::VectorViewIterator
позволяют использовать циклы и алгоритмы, такие как range for
с контейнером IVector<T>
. Но элементы IVector
нельзя получить доступ через разыменовку указателя C++, их можно получить доступ только через методы GetAt
и методы SetAt
. Таким образом, эти итераторы используют прокси-классы Platform::Details::VectorProxy<T>
и Platform::Details::ArrowProxy<T>
, предоставляя доступ к отдельным элементам через *
, ->
и []
операторы, как это требуется Стандартной библиотекой. Строго говоря, при использовании IVector<Person^> vec
типом *begin(vec)
является VectorProxy<Person^>
. Однако прокси-объект практически всегда прозрачен для кода. Эти прокси-объекты не документируются, поскольку предназначены исключительно для внутреннего пользования итераторами, однако полезно иметь представление о самом механизме работы.
При использовании цикла на основе for
диапазона по IVector
контейнерам используйте auto&&
для правильной привязки переменных итератора к VectorProxy
элементам. При использовании auto&
возникает предупреждение компилятора C4239 и VectorProxy
упоминается в тексте предупреждения.
На следующем рисунке показан цикл range for
с контейнерами IVector<Person^>
. Обратите внимание, что выполнение прекращается в точке останова на строке 64. В окне QuickWatch показывается, что переменная итератора p
на самом деле является VectorProxy<Person^>
, у которого есть переменные-члены m_v
и m_i
. Однако при вызове GetType
для этой переменной она возвращает идентичный тип в экземпляр Person
p2
. Вывод заключается в том, что хотя VectorProxy
и ArrowProxy
может отображаться в QuickWatch, отладчик некоторых ошибок компилятора или других местах, вам обычно не нужно явно кодировать для них.
Один из сценариев, в котором необходимо создать код для прокси-объекта, заключается в следующем: необходимо выполнить операцию dynamic_cast
с элементами, например при поиске объектов XAML определенного типа в коллекции элементов UIElement
. В этом случае необходимо сначала привести элемент к Platform::Object
^, а затем выполнить динамическое приведение типа.
void FindButton(UIElementCollection^ col)
{
// Use auto&& to avoid warning C4239
for (auto&& elem : col)
{
Button^ temp = dynamic_cast<Button^>(static_cast<Object^>(elem));
if (nullptr != temp)
{
// Use temp...
}
}
}
Map usage
В этом примере показано, как вставлять элементы и искать их в объекте Platform::Collections::Map
, а затем возвращать этот Map
как тип Windows::Foundation::Collections::IMapView
только для чтения.
//#include <collection.h>
//using namespace Platform::Collections;
//using namespace Windows::Foundation::Collections;
IMapView<String^, int>^ Class1::MapTest()
{
Map<String^, int>^ m = ref new Map<String^, int >();
m->Insert("Mike", 0);
m->Insert("Dave", 1);
m->Insert("Doug", 2);
m->Insert("Nikki", 3);
m->Insert("Kayley", 4);
m->Insert("Alex", 5);
m->Insert("Spencer", 6);
// PC::Map does not support [] operator
int i = m->Lookup("Doug");
return m->GetView();
}
Как правило, для реализации внутренних возможностей сопоставления предпочтительно использовать тип std::map
(из соображений производительности). Если вам необходимо передать контейнер через ABI, создайте Platform::Collections::Map
из std::map
и верните Map
как Windows::Foundation::Collections::IMap
. При попытке использования типа Map
в качестве открытого возвращаемого значения или параметра возникнет ошибка компилятора C3986. Эту ошибку можно исправить, заменив Map
объектом IMap
. В некоторых случаях (например, если вы не выполняете большого количества операций поиска или вставки и часто передаете коллекцию через интерфейс ABI) более рационально использовать класс Platform::Collections::Map
с самого начала, не затрачивая ресурсы на преобразование типа объекта std::map
. В любом случае следует избегать операций поиска и вставки в объектах IMap
, поскольку из всех трех типов он обладает самой низкой производительностью. Преобразование в IMap
следует выполнять только в момент передачи контейнера через интерфейс ABI.
Типы значений в объекте Map
Элементы в объекте Platform::Collections::Map
упорядочены. Любой элемент, хранящийся в Map
, должен поддерживать сравнение на меньше со строгим слабым упорядочением, либо неявно, либо с помощью предоставленного настраиваемого std::less
компаратора. Скалярные типы поддерживают сравнение неявно. Для нескалярных типов значений, таких как Windows::Foundation::DateTime
, или для пользовательских вариантов сравнения (например, objA->UniqueID < objB->UniqueID
) необходимо определять специальный алгоритм сравнения.
Collection types
Коллекции подразделяются на четыре категории: изменяемые и доступные только для чтения версии последовательных и ассоциативных коллекций. Кроме того, C++/CX улучшает коллекции, предоставляя три класса итератора, упрощающие доступ к коллекциям.
Элементы модифицируемой коллекции могут быть изменены, но элементы коллекции только для чтения, которая называется представлением, можно только прочитать. Элементы Platform::Collections::Vector
или Platform::Collections::VectorView
коллекции можно обработать с помощью итератора и индекса коллекции Vector::GetAt
. К элементам ассоциативной коллекции можно обращаться, используя коллекцию Map::Lookup
и ключ.
Platform::Collections::Map
Класс
Изменяемая ассоциативная коллекция. Элементы объекта Map представляют собой пары "ключ-значение". Поддерживается как поиск значения по связанному с ним ключу, так и перебор всех пар "ключ-значение".
В классахMap
и MapView
используется шаблон <K, V, C = std::less<K>>
; таким образом, алгоритм сравнения можно изменять. Кроме того, в классах Vector
и VectorView
используется шаблон <T, E = std::equal_to<T>>
, поэтому поведение метода IndexOf()
можно изменять. Это важно в основном для объектов Vector
и VectorView
, содержащих структуры значения. Например, чтобы создать Vector<Windows::Foundation::DateTime>
объект, необходимо предоставить пользовательский компаратор, так как DateTime не перегружает ==
оператор.
Platform::Collections::MapView
Класс
Версия объекта Map
только для чтения.
Platform::Collections::Vector
Класс
Изменяемая коллекция последовательностей.
Vector<T>
поддерживает случайный доступ с постоянной временной сложностью и операции с амортизированной временной сложностью Append
.
Platform::Collections::VectorView
Класс
Версия объекта Vector
только для чтения.
Platform::Collections::InputIterator
Класс
Итератор STL, отвечающий требованиям итератора ввода STL.
Platform::Collections::VectorIterator
Класс
Итератор STL, отвечающий требованиям изменяемого итератора произвольного доступа STL.
Platform::Collections::VectorViewIterator
Класс
Итератор STL, удовлетворяющий требованиям итератора случайного доступа STL const
.
Функции begin() и end()
Чтобы упростить использование STL для обработки Vector
, VectorView
, Map
, MapView
и произвольных Windows::Foundation::Collections
объектов, C++/CX поддерживает перегрузки функций begin
и end
, которые являются немемберными.
В следующей таблице перечислены все доступные итераторы и функции.
Iterators | Functions |
---|---|
Platform::Collections::VectorIterator<T> (Внутренне хранит Windows::Foundation::Collections::IVector<T> и int .) |
begin
/
end (Windows::Foundation::Collections::IVector<T> ) |
Platform::Collections::VectorViewIterator<T> (Внутренние хранилища IVectorView<T> ^ и int .) |
begin
/
end (IVectorView<T> ^) |
Platform::Collections::InputIterator<T> (Внутренне хранит IIterator<T> ^ и T .) |
begin
/
end (IIterable<T> ) |
Platform::Collections::InputIterator<IKeyValuePair<K, V>^> (Внутренние хранилища IIterator<T> ^ и T .) |
begin
/
end (IMap<K,V> ) |
Platform::Collections::InputIterator<IKeyValuePair<K, V>^> (Внутренне хранит IIterator<T> ^ и T .) |
begin
/
end (Windows::Foundation::Collections::IMapView ) |
События изменения коллекций
КлассыVector
и Map
поддерживают привязку данных в коллекциях XAML за счет реализации событий, которые возникают при изменении или сбросе объекта коллекции, а также при вставке, удалении или изменении любого элемента коллекции. Можно разрабатывать собственные типы, поддерживающие привязку данных, но нельзя наследовать от типов Map
и Vector
, так как эти типы запечатаны.
Windows::Foundation::Collections::VectorChangedEventHandler
и Windows::Foundation::Collections::MapChangedEventHandler
делегаты указывают сигнатуры для обработчиков событий для событий изменения коллекции. Публичный Windows::Foundation::Collections::CollectionChange
класс перечисления и Platform::Collections::Details::MapChangedEventArgs
и Platform::Collections::Details::VectorChangedEventArgs
ref классы хранят аргументы событий, чтобы определить, что вызвало событие.
*EventArgs
Типы определяются в Details
пространстве имен, так как вам не нужно создавать или использовать их явным образом при использовании Map
илиVector
.