Delen via


Verzamelingen (C++/CX)

In een C++/CX-programma kunt u gratis gebruikmaken van STL-containers (Standard Template Library) of een ander door de gebruiker gedefinieerd verzamelingstype. Wanneer u verzamelingen echter heen en weer doorgeeft via de binaire interface van de Windows Runtime-toepassing (ABI), bijvoorbeeld naar een XAML-besturingselement of een JavaScript-client, moet u typen Windows Runtime-verzamelingen gebruiken.

De Windows Runtime definieert de interfaces voor verzamelingen en gerelateerde typen, en C++/CX biedt de concrete C++-implementaties in het headerbestand collection.h. In deze afbeelding ziet u de relaties tussen de verzamelingstypen:

diagram van C plus plus C X overervingsboom voor verzamelingstypen.

Vectorgebruik

Wanneer uw klasse een reekscontainer moet doorgeven aan een ander Windows Runtime-onderdeel, gebruikt u Windows::Foundation::Collections:: IVector<T> als parameter of retourtype, en Platform::Collections::Vector<T> als de concrete implementatie. Als u probeert een Vector-type te gebruiken in een publieke retourwaarde of parameter, treedt de compilerfout C3986 op. U kunt de fout oplossen door de Vector te wijzigen in een IVector.

Belangrijk

Als u een reeks binnen uw eigen programma doorgeeft, gebruikt u Vector of std::vector omdat ze efficiënter zijn dan IVector. Gebruik IVector alleen wanneer u de container doorgeeft aan de ABI.

Het Windows Runtime-typesysteem biedt geen ondersteuning voor het concept van gelabelde matrices en daarom kunt u geen IVector<Platform::Array<T>> doorgeven als een retourwaarde of methodeparameter. Als u een gekartelde array of een sequentie van sequenties wilt doorgeven aan de ABI, gebruikt u IVector<IVector<T>^>.

Vector<T> biedt de methoden die nodig zijn voor het toevoegen, verwijderen en openen van items in de verzameling, en deze is impliciet converteerbaar naar IVector<T>. U kunt ook STL-algoritmen gebruiken op exemplaren van Vector<T>. In het volgende voorbeeld ziet u een aantal basisgebruiken. De beginfunctie en eindfunctie hier zijn afkomstig uit de Platform::Collections naamruimte, niet de std naamruimte.

#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();
}

Als u bestaande code hebt die gebruikmaakt van std::vector en u deze opnieuw wilt gebruiken in een Windows Runtime-onderdeel, gebruikt u slechts een van de Vector constructors die een std::vector of een paar iterators nodig hebben om een Vector te maken op het moment waarop u de verzameling doorgeeft over de ABI. In het volgende voorbeeld zie je hoe je met de Vector-verplaatsingsconstructor efficiënt initialiseert vanuit een std::vector. Na de verplaatsingsbewerking is de oorspronkelijke vec variabele niet meer geldig.

//#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));
}

Als u een vector van tekenreeksen hebt die u later moet doorgeven aan de ABI, moet u beslissen of u de tekenreeksen in eerste instantie wilt maken als std::wstring types of als Platform::String^ types. Als u veel verwerking op de tekenreeksen moet uitvoeren, gebruikt u wstring. Anders maakt u de tekenreeksen als Platform::String^ typen en vermijdt u de kosten voor het later converteren ervan. U moet ook bepalen of u deze tekenreeksen intern in een std:vector of Platform::Collections::Vector wilt plaatsen. Als algemene praktijk gebruikt u std::vector en maakt u er vervolgens alleen een Platform::Vector van wanneer u de container doorgeeft over de ABI.

Waardetypen in Vector

Elk element dat moet worden opgeslagen in een Platform::Collections::Vector moet ondersteuning bieden voor gelijkheidsvergelijking, impliciet of met behulp van een aangepaste std::equal_to comparator die u opgeeft. Alle referentietypen en alle scalaire typen ondersteunen impliciet gelijkheidsvergelijkingen. Voor niet-scalaire waardetypen zoals Windows::Foundation::D ateTimeof voor aangepaste vergelijkingen, bijvoorbeeld objA->UniqueID == objB->UniqueID, moet u een aangepast functieobject opgeven.

VectorProxy-elementen

Platform::Collections::VectorIterator en Platform::Collections::VectorViewIterator maken het mogelijk om range for lussen en algoritmen, zoals bijv. std::sort, te gebruiken met een IVector<T> container. Maar IVector elementen kunnen niet worden benaderd via C++-aanwijzerdereferentie; toegang kan alleen worden verkregen via de GetAt- en SetAt- methoden. Daarom gebruiken deze iterators de proxyklassen Platform::Details::VectorProxy<T> en Platform::Details::ArrowProxy<T> om toegang te bieden tot de afzonderlijke elementen via *, ->en [] operators, zoals vereist door de standaardbibliotheek. Strikt genomen, gezien een IVector<Person^> vec, is het type *begin(vec)VectorProxy<Person^>. Het proxyobject is echter bijna altijd transparant voor uw code. Deze proxyobjecten worden niet gedocumenteerd omdat ze alleen voor intern gebruik door de iterators worden gebruikt, maar het is handig om te weten hoe het mechanisme werkt.

Wanneer u een bereikgebaseerde for lus over IVector containers gebruikt, gebruikt u auto&& om de iteratorvariabele in te schakelen om de VectorProxy-elementen correct te binden. Als u auto&gebruikt, wordt er een compilerwaarschuwing C4239- gegenereerd en wordt VectoryProxy vermeld in de waarschuwingstekst.

De volgende illustratie toont een range for lus over een IVector<Person^>. U ziet dat de uitvoering is gestopt op het onderbrekingspunt op regel 64. In het venster QuickWatch ziet u dat de iteratorvariabele p in feite een VectorProxy<Person^> is met m_v en m_i lidvariabelen. Wanneer u echter GetType aanroept voor deze variabele, wordt het identieke type geretourneerd aan het Person exemplaar p2. Het leerpunt is dat hoewel VectorProxy en ArrowProxy in QuickWatch-, het foutopsporingsprogramma, bepaalde compilerfouten of andere locaties kunnen verschijnen, u doorgaans niet expliciet voor hen hoeft te coderen.

Schermopname van het debuggen van VectorProxy in een op bereik gebaseerde for-lus.

Een scenario waarin u moet coderen rond het proxyobject is wanneer u een dynamic_cast op de elementen moet uitvoeren, bijvoorbeeld wanneer u op zoek bent naar XAML-objecten van een bepaald type in een UIElement elementverzameling. In dit geval moet u eerst het element casten naar Platform::Object^ en vervolgens de dynamische cast uitvoeren:

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...
        }
    }
}

Gebruik van kaarten

In dit voorbeeld ziet u hoe u items invoegt en opzoekt in een Platform::Collections::Mapen de Map retour geeft als een alleen-lezen type 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();
   
}

Over het algemeen geeft u voor interne kaartfunctionaliteit de voorkeur aan het std::map type om prestatie-redenen. Als u de container moet doorgeven aan de ABI, maakt u een Platform::Collections::Map uit de std::map en retourneert u de Map als een Windows::Foundation::Collections::IMap. Als u probeert een type Map te gebruiken in een publieke retourwaarde of parameter, treedt compilerfout C3986 op. U kunt de fout oplossen door de Map te wijzigen in een IMap. In sommige gevallen, bijvoorbeeld als u niet een groot aantal zoekacties of invoegingen maakt en u de verzameling vaak doorgeeft aan de ABI, kan het minder duur zijn om vanaf het begin Platform::Collections::Map te gebruiken en de kosten voor het converteren van de std::mapte voorkomen. Vermijd in ieder geval opzoek- en invoegbewerkingen op een IMap omdat deze het minst presterende van de drie typen zijn. Converteer naar IMap alleen wanneer u de container door de ABI geeft.

Waardetypen in Kaart

Elementen in een Platform::Collections::Map zijn gerangschikt. Elk element dat moet worden opgeslagen in een Map moet ondersteuning bieden voor minder dan vergelijking met strikte zwakke volgorde, impliciet of met behulp van een aangepaste stl::less comparator die u opgeeft. Scalaire typen ondersteunen impliciet de vergelijking. Voor niet-scalaire waardetypen, zoals Windows::Foundation::DateTime, of voor aangepaste vergelijkingen, bijvoorbeeld objA->UniqueID < objB->UniqueID, moet u een aangepaste vergelijking opgeven.

Verzamelingstypen

Verzamelingen worden onderverdeeld in vier categorieën: wijzigbare versies en alleen-lezen versies van reeksverzamelingen en associatieve verzamelingen. Daarnaast verbetert C++/CX verzamelingen door drie iteratorklassen te bieden die de toegang tot verzamelingen vereenvoudigen.

Elementen van een wijzigbare verzameling kunnen worden gewijzigd, maar elementen van een alleen-lezenverzameling, ook wel een weergavegenoemd, kunnen alleen worden gelezen. Elementen van een Platform::Collections::Vector ofPlatform::Collections::VectorView verzameling zijn toegankelijk met behulp van een iterator of de Vector::GetAt- en een index van de verzameling. Elementen van een associatieve verzameling kunnen worden geopend met behulp van de Map::Lookup en een sleutel van de verzameling.

Platform::Collecties::Kaart klasse
Een wijzigbare, associatieve verzameling. Kaartelementen zijn sleutel-waardeparen. Het opzoeken van een sleutel om de bijbehorende waarde op te halen en het doorlopen van alle sleutel-waardeparen wordt beide ondersteund.

Map en MapView zijn gebaseerd op <K, V, C = std::less<K>>; daarom kunt u de comparator aanpassen. Daarnaast worden Vector en VectorView op <T, E = std::equal_to<T>> sjabloon gemaakt, zodat u het gedrag van IndexOf()kunt aanpassen. Dit is vooral belangrijk voor Vector en VectorView van waardestructuren. Als u bijvoorbeeld een Vector<Windows::Foundation::D ateTime>wilt maken, moet u een aangepaste comparator opgeven omdat DateTime de operator == niet overbelast.

Platform::Collections::MapView-klasse
Een lees-alleen versie van een Map.

Platform::Collections::Vector-klasse
Een wijzigbare reeksverzameling. Vector<T> biedt ondersteuning voor constante willekeurige toegang en afgeschreven constante tijd toevoegbewerkingen.

Platform::Collections::VectorView-klasse
Een alleen-lezen-modus van een Vector.

Platform::Collections::InputIterator-klasse
Een STL-iterator die voldoet aan de vereisten van een STL-invoer-iterator.

Platform::Collections::VectorIterator-klasse
Een STL-iterator die voldoet aan de vereisten van een STL-muteerbare iterator voor willekeurige toegang.

Platform::Collections::VectorViewIterator-klasse
Een STL-iterator die voldoet aan de vereisten van een STL-const iterator voor willekeurige toegang.

de functies begin() en end()

Om het gebruik van de STL te vereenvoudigen voor het verwerken van Vector, VectorView, Map, MapViewen willekeurige Windows::Foundation::Collections objecten, ondersteunt C++/CX overbelastingen van de en eindfunctie niet-lidfuncties.

De volgende tabel bevat de beschikbare iterators en functies.

Iterators (herhalingsmechanismen) Functies
Platform::Collections::VectorIterator<T>

(Slaat intern Windows::Foundation::Collections:: IVector<T> en int op.)
begin/ einde van(Windows::Foundation::Collections:: IVector<T>)
Platform::Collections::VectorViewIterator<T>

(Slaat intern IVectorView<T>^ en int op.)
begin/ (IVectorView<T>^)
Platform::Collections::InputIterator<T>

(Slaat intern IIterator<T>^ en T.)
begin/ (IIterable<T>)
Platform::Collections::InputIterator<IKeyValuePair<K, V>^>

(Slaat intern IIterator<T>^ en T.)
begin/ (IMap<K,V>.
Platform::Collections::InputIterator<IKeyValuePair<K, V>^>

(Slaat intern IIterator<T>^ en T.)
begin/ eind (Windows::Foundation::Collections::IMapView)

Gebeurtenissen van verzamelingswijziging

Vector en Map ondersteuning bieden voor gegevensbinding in XAML-verzamelingen door gebeurtenissen te implementeren die optreden wanneer een verzamelingsobject wordt gewijzigd of opnieuw wordt ingesteld, of wanneer een element van een verzameling wordt ingevoegd, verwijderd of gewijzigd. U kunt uw eigen typen schrijven die ondersteuning bieden voor gegevensbinding, hoewel u niet kunt overnemen van Map of Vector omdat deze typen zijn verzegeld.

De Windows::Foundation::Collections::VectorChangedEventHandler en Windows::Foundation::Collections::MapChangedEventHandler gedelegeerden specificeren de signaturen voor gebeurtenishandlers voor wijziging van verzamelingen. De Windows::Foundation::Collections::CollectionChange openbare enum klasse en de Platform::Collection::Details::MapChangedEventArgs en Platform::Collections::Details::VectorChangedEventArgs referentieklassen slaan de gebeurtenisargumenten op om te bepalen wat de oorzaak van de gebeurtenis is. De *EventArgs typen worden gedefinieerd in de Details naamruimte, omdat u deze niet expliciet hoeft te maken of gebruiken wanneer u Map of Vectorgebruikt.

Zie ook

Typesysteem
C++/CX Taalreferentie
verwijzing naar naamruimten