Kolekce (C++/CX)
V programu C++/CX můžete bezplatně používat kontejnery STL (Standard Template Library) nebo jakýkoli jiný uživatelem definovaný typ kolekce. Když však předáváte kolekce tam a zpět přes prostředí Windows Runtime binární rozhraní aplikace (ABI), například do ovládacího prvku XAML nebo javascriptového klienta, musíte použít prostředí Windows Runtime typy kolekcí.
Prostředí Windows Runtime definuje rozhraní pro kolekce a související typy a C++/CX poskytuje konkrétní implementace jazyka C++ v souboru hlavičky collection.h. Tento obrázek znázorňuje vztahy mezi typy kolekcí:
Třída Platform::Collections::Vector se podobá třídě std::vector.
Třída Platform::Collections::Map se podobá třídě std::map.
Platform::Collections::VectorView třída a Platform::Collections::MapView třídy jsou verze
Vector
aMap
.Iterátory jsou definovány v oboru názvů Platform::Collections. Tyto iterátory splňují požadavky na iterátory STL a umožňují použití std::find, std::count_if a dalších algoritmů STL v libovolném typu rozhraní Windows::Foundation::Collections typ rozhraní nebo Platform::Collections konkrétní typ. To například znamená, že můžete iterovat kolekci v prostředí Windows Runtime komponentě vytvořené v jazyce C# a použít na ni algoritmus STL.
Důležité
Iterátory
VectorIterator
proxy serveru aVectorViewIterator
využívají objektyVectoryProxy<T>
proxy serveru aArrowProxy<T>
umožňují použití s kontejnery STL. Další informace naleznete v části VectorProxy elementy dále v tomto článku.Typy kolekcí C++/CX podporují stejnou bezpečnost vláken, že kontejnery STL podporují.
Windows::Foundation::Collections::IObservableVector a Windows::Foundation::Collections::IObservableMap definují události, které se aktivují při změně kolekce různými způsoby. Implementací těchto rozhraní platform::Collections::Map a Platform::Collections::Vector podporují vazby dat s kolekcemi XAML. Pokud máte
Vector
například data svázaná s objektemGrid
, při přidání položky do kolekce se změna projeví v uživatelském rozhraní mřížky.
Použití vektoru
Pokud vaše třída musí předat sekvenční kontejner jiné prostředí Windows Runtime komponentě, použijte jako konkrétní implementaci Windows::Foundation::Collections:: IVector<T> jako parametr nebo návratový typ a Platform::Collections::Vector<T>. Pokud se pokusíte použít Vector
typ ve veřejné návratové hodnotě nebo parametru, vyvolá se chyba kompilátoru C3986. Chybu můžete opravit změnou na Vector
položku IVector
.
Důležité
Pokud předáváte sekvenci v rámci vlastního programu, použijte buď Vector
nebo std::vector
proto, že jsou efektivnější než IVector
. Použijte IVector
pouze v případech, kdy kontejner předáváte přes ABI.
Systém typů prostředí Windows Runtime nepodporuje koncept agregovaných polí, a proto nelze předat jako návratovou IVector<Platform::Array<T>>
hodnotu nebo parametr metody. Pokud chcete předat agregované pole nebo posloupnost sekvencí napříč ABI, použijte IVector<IVector<T>^>
.
Vector<T>
poskytuje metody potřebné pro přidávání, odebírání a přístup k položkám v kolekci a implicitně se konvertibilní na IVector<T>
. Můžete také použít algoritmy STL na instancích Vector<T>
. Následující příklad ukazuje některé základní použití. Počáteční funkce a koncová funkce jsou zde z Platform::Collections
oboru názvů, nikoli std
z oboru názvů.
#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();
}
Pokud máte existující kód, který se používá std::vector
a chcete ho znovu použít v prostředí Windows Runtime komponentě, stačí použít jeden z Vector
konstruktorů, který vezme std::vector
nebo pár iterátorů k vytvoření Vector
kolekce v místě, kde předáváte kolekci přes ABI. Následující příklad ukazuje, jak použít Vector
konstruktor move pro efektivní inicializaci z objektu std::vector
. Po operaci vec
přesunutí už původní proměnná není platná.
//#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));
}
Pokud máte vektor řetězců, které musíte v určitém budoucnosti předat přes ABI, musíte se rozhodnout, jestli chcete řetězce vytvořit původně jako std::wstring
typy nebo jako Platform::String^
typy. Pokud musíte na řetězcích provádět velké množství zpracování, použijte wstring
. V opačném případě vytvořte řetězce jako Platform::String^
typy a vyhněte se nákladům na jejich pozdější převod. Musíte se také rozhodnout, jestli se mají tyto řetězce vložit do nebo std:vector
Platform::Collections::Vector
interně. Obecně platí, že ho použijete std::vector
a pak vytvoříte Platform::Vector
jenom v případě, že kontejner předáte přes ABI.
Typy hodnot v vektoru
Jakýkoli prvek, který se má uložit v platformě::Collections::Vector , musí podporovat porovnání rovnosti, a to buď implicitně, nebo pomocí vlastního porovnávače std::equal_to komparátoru, který zadáte. Všechny referenční typy a všechny skalární typy implicitně podporují porovnání rovnosti. Pro jiné než skalární typy hodnot, například Windows::Foundation::D ateTime, nebo pro vlastní porovnání – například objA->UniqueID == objB->UniqueID
– musíte zadat vlastní objekt funkce.
VectorProxy – prvky
Platform::Collections::VectorIterator a Platform::Collections::VectorViewIterator umožňují používat range for
smyčky a algoritmy jako std::sort s kontejnerem IVector<T> . Prvky ale IVector
nelze získat přístup přes dereference ukazatele jazyka C++. K nim lze přistupovat pouze prostřednictvím metod GetAt a SetAt . Proto tyto iterátory používají třídy Platform::Details::VectorProxy<T>
proxy a Platform::Details::ArrowProxy<T>
poskytují přístup k jednotlivým prvkům prostřednictvím *operátorů ->, a [] podle požadavků standardní knihovny. Přísně řečeno, vzhledem IVector<Person^> vec
k , typ *begin(vec)
je VectorProxy<Person^>
. Objekt proxy serveru je však téměř vždy transparentní pro váš kód. Tyto proxy objekty nejsou zdokumentované, protože jsou určené pouze pro interní použití iterátory, ale je užitečné vědět, jak mechanismus funguje.
Pokud používáte smyčku založenou na for
rozsahu nad IVector
kontejnery, použijte auto&&
k povolení správné vazby proměnné iterátoru VectorProxy
s prvky. Pokud použijete auto&
, upozornění kompilátoru C4239 je vyvolána a VectoryProxy
je uvedena v textu upozornění.
Následující obrázek znázorňuje smyčku range for
přes .IVector<Person^>
Všimněte si, že spuštění je zastaveno na zarážce na řádku 64. Okno QuickWatch ukazuje, že proměnná p
iterátoru je ve skutečnosti proměnná VectorProxy<Person^>
, která má m_v
a m_i
členské proměnné. Při volání GetType
této proměnné však vrátí stejný typ jako Person
instance p2
. Poznatky jsou, že i když VectorProxy
a ArrowProxy
může se objevit v QuickWatch, ladicí program určité chyby kompilátoru nebo na jiných místech, obvykle pro ně nemusíte explicitně kódovat.
Jedním ze scénářů, ve kterém je nutné kódovat kolem objektu proxy, je situace, kdy je třeba provést s dynamic_cast
elementy – například když hledáte objekty XAML určitého typu v UIElement
kolekci elementů. V tomto případě musíte nejprve přetypovat prvek na Platform::Object^ a pak provést dynamické přetypování:
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...
}
}
}
Využití mapy
Tento příklad ukazuje, jak vložit položky a vyhledat je v platformě::Collections::Map a vrátit Map
je jako typ 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();
}
Obecně platí, že u interních funkcí mapování dáváte přednost std::map
typu z důvodů výkonu. Pokud potřebujete kontejner předat přes ABI, vytvořte platformu ::Collections::Map z objektu std::map a vraťte ho Map
jako Windows::Foundation::Collections::IMap. Pokud se pokusíte použít Map
typ ve veřejné návratové hodnotě nebo parametru, vyvolá se chyba kompilátoru C3986. Chybu můžete opravit změnou na Map
položku IMap
. V některých případech , například pokud nevytváření velkého počtu vyhledávání nebo vložení a předáváte kolekci napříč ABI často , může být levnější použít Platform::Collections::Map
od začátku a vyhnout se nákladům na převod std::map
. V každém případě se vyhněte operacím vyhledávání a vkládání, IMap
protože tyto operace jsou nejméně výkonné ze tří typů. IMap
Převeďte ho jenom v okamžiku, kdy kontejner předáváte přes ABI.
Typy hodnot v mapě
Prvky v platform::Collections::Map jsou seřazené. Jakýkoli prvek, který má být uložen v porovnání Map
s přísným slabým řazením, musí podporovat menší než porovnání, a to buď implicitně, nebo pomocí vlastního stl::less srovnávacího nástroje, který zadáte. Skalární typy podporují implicitně porovnání. Pro jiné než skalární typy hodnot, jako Windows::Foundation::DateTime
jsou například nebo pro vlastní porovnání, objA->UniqueID < objB->UniqueID
musíte zadat vlastní srovnávací program.
Typy kolekcí
Kolekce spadají do čtyř kategorií: upravitelné verze a verze sekvenčních kolekcí a asociativních kolekcí jen pro čtení. Kromě toho C++/CX vylepšuje kolekce tím, že poskytuje tři třídy iterátoru, které zjednodušují přístup ke kolekcím.
Prvky upravitelné kolekce lze změnit, ale prvky kolekce jen pro čtení, které se označují jako zobrazení, lze číst pouze. K prvkům platformy::Collections::Vector neboPlatform::Collections::VectorView můžete přistupovat pomocí iterátoru nebo vektoru kolekce::GetAt a indexu. K prvkům asociativní kolekce lze přistupovat pomocí map::lookup kolekce a klíče.
Platform::Collections::Map – třída
Upravitelná asociativní kolekce. Prvky mapy jsou páry klíč-hodnota. Vyhledání klíče pro načtení přidružené hodnoty a iterace prostřednictvím všech párů klíč-hodnota jsou podporovány.
Map
a MapView
jsou upraveny <K, V, C = std::less<K>>
na ; proto můžete upravit srovnávací program. Kromě toho Vector
a VectorView
jsou šablonovány <T, E = std::equal_to<T>>
tak, aby bylo možné přizpůsobit chování IndexOf()
. To je důležité hlavně pro Vector
struktury hodnot.VectorView
Chcete-li například vytvořit Vektor<Windows::Foundation::D ateTime>, musíte zadat vlastní srovnávací program, protože DateTime nepřetěžuje operátor == .
Platform::Collections::MapView – třída
Verze jen pro Map
čtení .
Platform::Collections::Vector – třída
Upravitelná kolekce sekvencí. Vector<T>
podporuje náhodný přístup k konstantě a amortizovaný-konstantní-čas přidávací operace..
Platform::Collections::VectorView – třída
Verze jen pro Vector
čtení .
Platform::Collections::InputIterator – třída
Iterátor STL, který splňuje požadavky vstupního iterátoru STL.
Platform::Collections::VectorIterator – třída
Iterátor STL, který splňuje požadavky iterátoru náhodného přístupu STL.
Platform::Collections::VectorViewIterator – třída
Iterátor STL, který splňuje požadavky iterátoru náhodného přístupu STL const
.
begin() a end()
Pro zjednodušení použití STL ke zpracování Vector
, , VectorView
, Map
MapView
, a libovolných Windows::Foundation::Collections
objektů, C++/CX podporuje přetížení počáteční funkce a koncové funkce nečlenské funkce.
Následující tabulka uvádí dostupné iterátory a funkce.
Iterátory | Funkce |
---|---|
Platform::Collections::VectorIterator<T> (Interně ukládá Windows::Foundation::Collections:: IVector<T> a int.) |
begin/ end(Windows::Foundation::Collections:: IVector<T>) |
Platform::Collections::VectorViewIterator<T> (Interně ukládá IVectorView<T>^ a int.) |
začátek/ (IVectorView<T>^) |
Platform::Collections::InputIterator<T> (Interně ukládá IIterator<T>^ a T.) |
začátek/ (IIterable<T)> |
Platform::Collections::InputIterator<IKeyValuePair<K, V>^> (Interně ukládá IIterator<T>^ a T.) |
začátek/ (IMap<K,V.> |
Platform::Collections::InputIterator<IKeyValuePair<K, V>^> (Interně ukládá IIterator<T>^ a T.) |
začátek/ (Windows::Foundation::Collections::IMapView) |
Události změn kolekce
Vector
a Map
podporují vazbu dat v kolekcích XAML implementací událostí, ke kterým dochází při změně nebo resetování objektu kolekce nebo při vložení, odebrání nebo změně jakéhokoli prvku kolekce. Můžete napsat vlastní typy, které podporují vazbu dat, i když z nich nemůžete dědit Map
nebo Vector
protože tyto typy jsou zapečetěné.
Windows::Foundation::Collections::VectorChangedEventHandler a Windows::Foundation::Collections::MapChangedEventHandler delegáti určují podpisy obslužných rutin událostí pro události změny kolekce. Windows ::Foundation::Collections::CollectionChange veřejná třída výčtu a Platform::Collection::Details::MapChangedEventArgs
ref Platform::Collections::Details::VectorChangedEventArgs
třídy, uložte argumenty události, abyste zjistili, co způsobilo událost. Typy *EventArgs
jsou definovány v Details
oboru názvů, protože není nutné je vytvářet ani využívat explicitně při použití Map
nebo Vector
.
Viz také
Systém typů
Referenční zdroje k jazyku C++/CX
Referenční informace o oborech názvů