Partilhar via


Coleções (C++/CX)

Em um programa C++/CX, você pode usar gratuitamente contêineres STL (Standard Template Library) ou qualquer outro tipo de coleção definido pelo usuário. No entanto, quando você passa coleções de um lado para o outro pela ABI (interface binária do aplicativo) do Tempo de Execução do Windows — por exemplo, para um controle XAML ou para um cliente JavaScript — você deve usar tipos de coleção do Tempo de Execução do Windows.

O Tempo de Execução do Windows define as interfaces para coleções e tipos relacionados, e o C++/CX fornece as implementações concretas do C++ no arquivo de cabeçalho collection.h. Esta ilustração mostra as relações entre os tipos de coleção:

Diagrama da árvore de herança C mais C mais C X para tipos de coleção.

Uso de vetores

Quando a sua classe tiver que passar um contêiner de sequência para outro componente do Windows Runtime, use Windows::Foundation::Collections:: IVector<T> como parâmetro ou tipo de retorno, e Platform::Collections::Vector<T> como a implementação concreta. Se você tentar usar um tipo de Vector em um valor de retorno público ou parâmetro, o erro de compilador C3986 será gerado. Você pode corrigir o erro alterando o Vector para um IVector.

Importante

Se você estiver passando uma sequência dentro do seu próprio programa, use Vector ou std::vector porque eles são mais eficientes do que IVector. Use IVector apenas quando passar o container através da ABI.

O sistema do tipo Tempo de Execução do Windows não oferece suporte ao conceito de matrizes irregulares e, portanto, você não pode passar um IVector<Platform::Array<T>> como um valor de retorno ou parâmetro de método. Para passar uma matriz irregular ou uma sequência de sequências pela ABI, use IVector<IVector<T>^>.

Vector<T> fornece os métodos necessários para adicionar, remover e acessar itens na coleção, e é implicitamente conversível para IVector<T>. Você também pode usar algoritmos STL em instâncias de Vector<T>. O exemplo a seguir demonstra algum uso básico. A função início e a função fim aqui são do namespace Platform::Collections, não do namespace 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();
}

Se tiveres um código existente que usa std::vector e quiseres reutilizá-lo num componente Windows Runtime, basta usar um dos construtores Vector que recebe um std::vector ou um par de iteradores para construir um Vector quando passas a coleção pela ABI. O exemplo a seguir mostra como usar o construtor Vector move para inicialização eficiente a partir de um std::vector. Após a operação de movimentação, a variável vec original não é mais válida.

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

Se você tiver um vetor de cadeias de caracteres que você deve passar através da ABI em algum ponto futuro, você deve decidir se deseja criar as cadeias de caracteres inicialmente como tipos std::wstring ou como tipos Platform::String^. Se tiveres que fazer muito processamento nas cadeias de caracteres, usa wstring. Caso contrário, crie as cadeias de caracteres como tipos Platform::String^ e evite o custo de convertê-las posteriormente. Você também deve decidir se deseja colocar essas cadeias de caracteres em um std:vector ou Platform::Collections::Vector internamente. Como prática geral, utilize std::vector e só crie um Platform::Vector a partir dele ao passar o contentor pelo ABI.

Tipos de valor em Vetor

Qualquer elemento a ser armazenado em um Platform::Collections::Vector deve oferecer suporte à comparação de igualdade, quer implicitamente, quer utilizando um comparador de igualdade personalizado std::equal_to que você fornece. Todos os tipos de referência e todos os tipos escalares suportam implicitamente comparações de igualdade. Para tipos de valores não escalares, como Windows::Foundation::D ateTime, ou para comparações personalizadas, por exemplo, objA->UniqueID == objB->UniqueID—, você deve fornecer um objeto de função personalizado.

Elementos VectorProxy

Platform::Collections::VectorIterator e Platform::Collections::VectorViewIterator permitir o uso de loops de range for e algoritmos como std::sort com um contêiner IVector<T>. Mas IVector elementos não podem ser acessados através da desreferência de ponteiros em C++; eles podem ser acessados somente por meio dos métodos GetAt e SetAt. Portanto, esses iteradores usam as classes proxy Platform::Details::VectorProxy<T> e Platform::Details::ArrowProxy<T> para fornecer acesso aos elementos individuais por meio de operadores *, ->e [], conforme exigido pela Biblioteca Padrão. A rigor, dado um IVector<Person^> vec, o tipo de *begin(vec) é VectorProxy<Person^>. No entanto, o objeto proxy é quase sempre transparente para o seu código. Esses objetos proxy não são documentados porque são apenas para uso interno pelos iteradores, mas é útil saber como o mecanismo funciona.

Ao utilizar um ciclo de for baseado em intervalo em contentores IVector, utilize auto&& para permitir que a variável do iterador se associe corretamente aos elementos VectorProxy. Se você usar auto&, o aviso do compilador C4239 é gerado e VectoryProxy é mencionado no texto de aviso.

A ilustração a seguir mostra um loop de range for em um IVector<Person^>. Observe que a execução é interrompida no ponto de interrupção na linha 64. A janela QuickWatch mostra que a variável iteradora p é, na verdade, um VectorProxy<Person^> que tem m_v e m_i variáveis de membro. No entanto, quando você chama GetType nessa variável, ela retorna o tipo idêntico para a instância Personp2. A conclusão é que, embora VectorProxy e ArrowProxy possam aparecer no QuickWatch, no depurador, em certos erros do compilador ou em outros lugares, tu normalmente não precisas codificar explicitamente para eles.

Captura de tela da depuração de VectorProxy em um intervalo baseado em loop.

Um cenário em que você precisa codificar em torno do objeto proxy é quando você precisa executar uma dynamic_cast nos elementos — por exemplo, quando você está procurando objetos XAML de um tipo específico em uma coleção de elementos UIElement. Nesse caso, você deve primeiro converter o elemento para Platform::Object^ e, em seguida, executar a conversão dinâmica:

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

Utilização do mapa

Este exemplo mostra como inserir itens e procurá-los numa Platform::Collections::Mape, em seguida, retornar o Map como um tipo Windows::Foundation::Collections::IMapView somente leitura.

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

Em geral, para a funcionalidade de mapa interno, prefira o tipo std::map por motivos de desempenho. Se você tiver que passar o contêiner através da ABI, construa um Platform::Collections::Map a partir do std::map e retorne o Map como um Windows::Foundation::Collections::IMap. Se você tentar usar um tipo de Map em um valor de retorno público ou parâmetro, o erro de compilador C3986 será gerado. Você pode corrigir o erro alterando o Map para um IMap. Em alguns casos, por exemplo, se não estiveres a fazer um grande número de consultas ou inserções e estiveres a passar a coleção pela ABI com frequência, pode ser menos dispendioso usar o Platform::Collections::Map desde o início e evitar o custo de conversão do std::map. Em qualquer caso, evite realizar operações de pesquisa e inserção em um IMap, porque estas são as menos eficientes dos três tipos. Converta em IMap somente no ponto em que você passa o contêiner pela ABI.

Tipos de valor em mapa

Os elementos em uma Platform::Collections::Map são ordenados por definição. Qualquer elemento a ser armazenado em um Map deve suportar uma comparação de menor que com ordenação fraca estrita, seja implicitamente ou usando um comparador stl::less personalizado que você fornece. Os tipos escalares suportam a comparação implicitamente. Para tipos de valores não escalares, como Windows::Foundation::DateTime, ou para comparações personalizadas, por exemplo, objA->UniqueID < objB->UniqueID, você deve fornecer um comparador personalizado.

Tipos de recolha

As coleções se dividem em quatro categorias: versões modificáveis e versões somente leitura de coleções de sequências e coleções associativas. Além disso, o C++/CX aprimora as coleções fornecendo três classes iteradoras que simplificam o acesso às coleções.

Os elementos de uma coleção modificável podem ser alterados, mas os elementos de uma coleção de leitura apenas, que é conhecida como uma de exibição, só podem ser lidos. Elementos de uma Platform::Collections::Vetor ouPlatform::Collections::VectorView coleção pode ser acessada usando um iterador ou o e um índice Vetor::GetAt da coleção. Os elementos de uma coleção associativa podem ser acessados usando o Map::Lookup e uma chave da coleção.

Platform::Collections::Map class
Uma coleção modificável e associativa. Os elementos do mapa são pares chave-valor. A pesquisa de uma chave para recuperar seu valor associado e a iteração através de todos os pares chave-valor são suportadas.

Map e MapView são modeladas em <K, V, C = std::less<K>>; portanto, você pode personalizar o comparador. Além disso, Vector e VectorView são modeladas em <T, E = std::equal_to<T>> para que você possa personalizar o comportamento de IndexOf(). Isso é importante principalmente para Vector e VectorView de estruturas de valor. Por exemplo, para criar um Vector<Windows::Foundation::DateTime>, deve fornecer um comparador personalizado porque DateTime não tem a sobrecarga do operador == .

Plataforma::Coleções::VisãoMapa classe
Uma versão somente leitura de um Map.

Platform::Collections::Vector classe
Uma coleção de sequências modificáveis. Vector<T> suporta operações de acesso aleatório em tempo constante e de de tempo constante amortizado.

Platform::Collections::VectorView classe
Uma versão somente leitura de um Vector.

Platform::Collections::InputIterator classe
Um iterador STL que satisfaz os requisitos de um iterador de entrada STL.

Platform::Collections::VectorIterator classe
Um iterador STL que cumpre os requisitos de um iterador mutável de acesso aleatório STL.

Platform::Collections::VectorViewIterator classe
Um iterador STL que satisfaz os requisitos de um iterador STL const de acesso aleatório.

funções begin() e end()

Para simplificar o uso da STL para processar objetos de Windows::Foundation::CollectionsVector, VectorView, Map, MapViewe arbitrários, o C++/CX suporta sobrecargas do iniciar a Função e Função final funções não-membros.

A tabela a seguir lista os iteradores e funções disponíveis.

Iteradores Funções
Platform::Collections::VectorIterator<T>

(Internamente armazena Windows::Foundation::Collections:: IVector<T> e int.)
começar/ terminar(Windows::Foundation::Collections:: IVector<T>)
Platform::Collections::VectorViewIterator<T>

(Armazena internamente IVectorView<T>^ e int.)
começar/ terminar (IVectorView<T>^)
Platform::Collections::InputIterator<T>

(Armazena internamente IIterator<T>^ e T.)
começar/ terminar (IIterable<T>)
Platform::Collections::InputIterator<IKeyValuePair<K, V>^>

(Armazena internamente IIterator<T>^ e T.)
começar/ terminar (IMap<K,V>.
Platform::Collections::InputIterator<IKeyValuePair<K, V>^>

(Armazena internamente IIterator<T>^ e T.)
começar/ terminar (Windows::Foundation::Collections::IMapView)

Eventos de alteração em coleções

Vector e Map oferecem suporte à vinculação de dados em coleções XAML implementando eventos que ocorrem quando um objeto de coleção é alterado ou redefinido, ou quando qualquer elemento de uma coleção é inserido, removido ou alterado. Você pode escrever seus próprios tipos que suportam vinculação de dados, embora não possa herdar de Map ou Vector porque esses tipos são selados.

Os delegados Windows::Foundation::Collections::VectorChangedEventHandler e Windows::Foundation::Collections::MapChangedEventHandler especificam as assinaturas para manipuladores de eventos de alteração de coleção. O Windows::Foundation::Collections::CollectionChange classe enum pública e Platform::Collection::Details::MapChangedEventArgs e Platform::Collections::Details::VectorChangedEventArgs classes ref, armazenam os argumentos de evento para determinar o que causou o evento. Os tipos de *EventArgs são definidos no namespace Details porque você não precisa construí-los ou consumi-los explicitamente quando usa Map ou Vector.

Ver também

tipo de sistema
Referência da Linguagem C++/CX
Referência a Namespaces