Sdílet prostřednictvím


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í:

Diagram stromu dědičnosti pro typy kolekcí v C++ C X.

Použití vektoru

Pokud vaše třída musí předat sekvence kontejner do jiné součásti prostředí Windows Runtime, použijte Windows::Foundation::Collections::IVector<T> jako parametr nebo návratový typ a Platform::Collections::Vector<T> jako konkrétní implementaci. 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.

Important

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í. Funkce begin aend funkce jsou zde z Platform::Collections oboru názvů, nikoli z std 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::vectorPlatform::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ý má být uložen v Platform::Collections::Vector jazyce, musí podporovat porovnání rovnosti, a to buď implicitně, nebo pomocí vlastního std::equal_to srovnávacího nástroje, který zadáte. Všechny referenční typy a všechny skalární typy implicitně podporují porovnání rovnosti. Pro typy hodnot, které nejsou skalární, například Windows::Foundation::DateTime, nebo pro vlastní porovnávání, jako je objA->UniqueID == objB->UniqueID, musíte poskytnout objekt pro vlastní funkci.

VectorProxy – prvky

Platform::Collections::VectorIterator a Platform::Collections::VectorViewIterator umožňuje použití range for smyček a algoritmy jako std::sort s IVector<T> kontejnerem. Nelze ale přistupovat k prvkům IVector prostřednictvím dereference ukazatele v C++. Lze k nim přistupovat pouze prostřednictvím GetAt a SetAt metod. Proto tyto iterátory používají třídy Platform::Details::VectorProxy<T> proxy a Platform::Details::ArrowProxy<T> k poskytování přístupu k jednotlivým prvkům prostřednictvím *, -> a [] operátorů, jak to vyžaduje Standardní knihovna. Přísně řečeno, vzhledem IVector<Person^> veck , 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áno a VectorProxy je zmíněno 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. Závěr je, že i když se VectorProxy a ArrowProxy mohou objevit v QuickWatch, ladicím programu, určitých chybách kompilátoru nebo na jiných místech, obvykle pro ně nemusíte explicitně psát kód.

Snímek obrazovky ladění VectorProxy v rozsahu založeném na smyčce for

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::Mapa pak vrátit Map jako typ jen Windows::Foundation::Collections::IMapView pro čtení.

//#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 předat kontejner přes ABI, vytvořte Platform::Collections::Map z std::map a vraťte 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 ve struktuře Platform::Collections::Map jsou seřazené. Jakýkoli prvek, který má být uložen v Map, musí podporovat porovnání se striktním slabým řazením, buď implicitně, nebo pomocí vlastního std::less komparátoru, který zadáte. Skalární typy podporují implicitně porovnání. Pro jiné než skalární typy hodnot, jako Windows::Foundation::DateTimejsou například nebo pro vlastní porovnání, objA->UniqueID < objB->UniqueIDmusí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 Platform::Collections::Vector nebo Platform::Collections::VectorView kolekci je možné přistupovat pomocí iterátoru nebo kolekce Vector::GetAt a indexu. K prvkům asociativní kolekce lze přistupovat pomocí kolekce Map::Lookup a klíče.

třída Platform::Collections::Map
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 Vector<Windows::Foundation::DateTime>, musíte zadat vlastní srovnávací program, protože DateTime nepřetěžuje == operátor.

třída Platform::Collections::MapView
Verze jen pro Mapčtení .

třída Platform::Collections::Vector
Upravitelná kolekce sekvencí. Vector<T> podporuje náhodný přístup s konstantní časovou složitostí a amortizované operace s konstantní časovou složitostí Append.

třída Platform::Collections::VectorView
Verze jen pro Vectorčtení .

třída Platform::Collections::InputIterator
Iterátor STL, který splňuje požadavky vstupního iterátoru STL.

třída Platform::Collections::VectorIterator
Iterátor STL, který splňuje požadavky iterátoru náhodného přístupu STL.

třída Platform::Collections::VectorViewIterator
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í , , , a libovolných objektů, C++/CX podporuje přetížení nečlenských funkcí a .

Následující tabulka uvádí dostupné iterátory a funkce.

Iterators Functions
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.)
begin / end (IVectorView<T>^)
Platform::Collections::InputIterator<T>

(Interně ukládá IIterator<T>^ a T.)
begin / end (IIterable<T>)
Platform::Collections::InputIterator<IKeyValuePair<K, V>^>

(Interně ukládá IIterator<T>^ a T.)
begin / end (IMap<K,V>)
Platform::Collections::InputIterator<IKeyValuePair<K, V>^>

(Interně ukládá IIterator<T>^ a T.)
begin / end (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é.

Delegáti Windows::Foundation::Collections::VectorChangedEventHandler a Windows::Foundation::Collections::MapChangedEventHandler specifikují podpisy obslužných rutin pro události změny kolekce. Veřejná výčtová třída Windows::Foundation::Collections::CollectionChange a ref třídy Platform::Collections::Details::MapChangedEventArgs a Platform::Collections::Details::VectorChangedEventArgs ukládají argumenty události, aby bylo možné určit, 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í dokumentace jazyka C++/CX
Referenční příručka k jmenným prostorům