Koleksi (C++/CX)

Dalam program C++/CX, Anda dapat menggunakan kontainer Standard Template Library (STL) secara gratis, atau jenis koleksi lain yang ditentukan pengguna. Namun, ketika Anda meneruskan koleksi bolak-balik di seluruh antarmuka biner aplikasi Windows Runtime (ABI)—misalnya, ke kontrol XAML atau ke klien JavaScript—Anda harus menggunakan jenis koleksi Windows Runtime.

Windows Runtime mendefinisikan antarmuka untuk koleksi dan jenis terkait, dan C++/CX menyediakan implementasi C++ konkret dalam file header collection.h. Ilustrasi ini memperlihatkan hubungan antara jenis koleksi:

Diagram of C plus plus C X inheritance tree for collection types.

Penggunaan vektor

Ketika kelas Anda harus meneruskan kontainer urutan ke komponen Windows Runtime lain, gunakan Windows::Foundation::Collections:: IVector<T> sebagai parameter atau jenis pengembalian, dan Platform::Collections::Vector<T> sebagai implementasi konkret. Jika Anda mencoba menggunakan Vector jenis dalam nilai atau parameter pengembalian publik, kesalahan pengkompilasi C3986 akan dimunculkan. Anda dapat memperbaiki kesalahan dengan mengubah ke VectorIVector.

Penting

Jika Anda melewati urutan dalam program Anda sendiri, maka gunakan salah satu Vector atau std::vector karena mereka lebih efisien daripada IVector. Gunakan IVector hanya saat Anda meneruskan kontainer di seluruh ABI.

Sistem jenis Windows Runtime tidak mendukung konsep array berjatuhan dan oleh karena itu Anda tidak dapat meneruskan IVector<Platform::Array<T>> sebagai nilai pengembalian atau parameter metode. Untuk meneruskan array berjatuhan atau urutan urutan di seluruh ABI, gunakan IVector<IVector<T>^>.

Vector<T> menyediakan metode yang diperlukan untuk menambahkan, menghapus, dan mengakses item dalam koleksi, dan secara implisit dapat dikonversi ke IVector<T>. Anda juga dapat menggunakan algoritma STL pada instans Vector<T>. Contoh berikut menunjukkan beberapa penggunaan dasar. Fungsi awal dan fungsi akhir di sini berasal dari Platform::Collections namespace, bukan std namespace.

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

Jika Anda memiliki kode yang ada yang menggunakan std::vector dan Anda ingin menggunakannya kembali dalam komponen Windows Runtime, cukup gunakan salah Vector satu konstruktor yang mengambil std::vector atau sepasang iterator untuk membangun Vector pada titik di mana Anda meneruskan koleksi di seluruh ABI. Contoh berikut menunjukkan cara menggunakan konstruktor pemindahan Vector untuk inisialisasi yang std::vectorefisien dari . Setelah operasi pemindahan, variabel asli vec tidak lagi valid.

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

Jika Anda memiliki vektor string yang harus Anda lewati di ABI pada beberapa titik mendatang, Anda harus memutuskan apakah akan membuat string awalnya sebagai std::wstring jenis atau sebagai Platform::String^ jenis. Jika Anda harus melakukan banyak pemrosesan pada string, maka gunakan wstring. Jika tidak, buat string sebagai Platform::String^ jenis dan hindari biaya konversi nanti. Anda juga harus memutuskan apakah akan memasukkan string ini ke dalam std:vector atau Platform::Collections::Vector secara internal. Sebagai praktik umum, gunakan std::vector lalu buat Platform::Vector dari itu hanya ketika Anda meneruskan kontainer di seluruh ABI.

Jenis nilai di Vektor

Elemen apa pun yang akan disimpan dalam Platform::Collections::Vector harus mendukung perbandingan kesetaraan, baik secara implisit maupun dengan menggunakan komparator std kustom ::equal_to yang Anda sediakan. Semua jenis referensi dan semua jenis skalar secara implisit mendukung perbandingan kesetaraan. Untuk jenis nilai non-skalar seperti Windows::Foundation::D ateTime, atau untuk perbandingan kustom—misalnya, objA->UniqueID == objB->UniqueID—Anda harus menyediakan objek fungsi kustom.

Elemen VectorProxy

Platform::Collections::VectorIterator and Platform::Collections::VectorViewIterator memungkinkan penggunaan range for perulangan dan algoritma seperti std::sort dengan kontainer IVector<T> . Tetapi IVector elemen tidak dapat diakses melalui dereferensi pointer C++; elemen hanya dapat diakses melalui metode GetAt dan SetAt . Oleh karena itu, iterator ini menggunakan kelas Platform::Details::VectorProxy<T> proksi dan Platform::Details::ArrowProxy<T> untuk menyediakan akses ke elemen individu melalui *operator , ->, dan [], seperti yang diperlukan oleh Pustaka Standar. Secara ketat, diberikan IVector<Person^> vec, jenisnya *begin(vec) adalah VectorProxy<Person^>. Namun, objek proksi hampir selalu transparan dengan kode Anda. Objek proksi ini tidak didokumenkan karena hanya untuk penggunaan internal oleh iterator, tetapi berguna untuk mengetahui cara kerja mekanisme.

Saat Anda menggunakan perulangan berbasis for rentang melalui IVector kontainer, gunakan auto&& untuk mengaktifkan variabel iterator untuk mengikat dengan benar ke VectorProxy elemen. Jika Anda menggunakan auto&, peringatan kompilator C4239 dinaikkan dan VectoryProxy disebutkan dalam teks peringatan.

Ilustrasi berikut menunjukkan perulangan range for di atas IVector<Person^>. Perhatikan bahwa eksekusi dihentikan pada titik henti pada baris 64. Jendela QuickWatch menunjukkan bahwa variabel p iterator sebenarnya adalah VectorProxy<Person^> variabel yang memiliki m_v dan m_i anggota. Namun, ketika Anda memanggil GetType variabel ini, variabel mengembalikan jenis yang identik ke Person instans p2. Takeaway adalah bahwa meskipun VectorProxy dan ArrowProxy mungkin muncul di QuickWatch, debugger kesalahan kompilator tertentu, atau tempat lain, Anda biasanya tidak perlu secara eksplisit membuat kode untuk mereka.

Screenshot of debugging VectorProxy in a range based for loop.

Salah satu skenario di mana Anda harus membuat kode di sekitar objek proksi adalah ketika Anda harus melakukan dynamic_cast pada elemen—misalnya, ketika Anda mencari objek XAML dari jenis tertentu dalam UIElement koleksi elemen. Dalam hal ini, Anda harus terlebih dahulu melemparkan elemen ke Platform::Object^ dan kemudian melakukan pemeran dinamis:

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

Penggunaan peta

Contoh ini menunjukkan cara menyisipkan item dan mencarinya di Platform::Collections::Map, lalu mengembalikan Map sebagai Windows baca-saja ::Foundation::Collections::IMapView type.

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

Secara umum, untuk fungsionalitas peta internal, lebih suka jenis karena std::map alasan performa. Jika Anda harus meneruskan kontainer di seluruh ABI, buat Platform::Collections::Map dari std::map dan kembalikan Map sebagai Windows::Foundation::Collections::IMap. Jika Anda mencoba menggunakan Map jenis dalam nilai atau parameter pengembalian publik, kesalahan pengkompilasi C3986 akan dimunculkan. Anda dapat memperbaiki kesalahan dengan mengubah ke MapIMap. Dalam beberapa kasus—misalnya, jika Anda tidak membuat sejumlah besar pencarian atau penyisipan, dan Anda sering meneruskan koleksi di seluruh ABI—mungkin lebih murah untuk digunakan Platform::Collections::Map dari awal dan menghindari biaya konversi std::map. Bagaimanapun, hindari operasi pencarian dan sisipkan pada karena IMap ini adalah performa paling sedikit dari tiga jenis. Konversi ke IMap hanya pada titik anda meneruskan kontainer di seluruh ABI.

Jenis nilai di Peta

Elemen dalam Platform::Collections::Map diurutkan. Elemen apa pun yang Map akan disimpan dalam harus mendukung perbandingan yang kurang dari dengan urutan yang lemah yang ketat, baik secara implisit atau dengan menggunakan stl kustom ::less comparator yang Anda sediakan. Jenis skalar mendukung perbandingan secara implisit. Untuk jenis nilai non-skalar seperti Windows::Foundation::DateTime, atau untuk perbandingan kustom—misalnya, objA->UniqueID < objB->UniqueID—Anda harus menyediakan komparator kustom.

Tipe koleksi

Koleksi termasuk dalam empat kategori: versi yang dapat dimodifikasi dan versi koleksi urutan baca-saja dan koleksi asosiatif. Selain itu, C++/CX meningkatkan koleksi dengan menyediakan tiga kelas iterator yang menyederhanakan akses koleksi.

Elemen koleksi yang dapat dimodifikasi dapat diubah, tetapi elemen koleksi baca-saja, yang dikenal sebagai tampilan, hanya dapat dibaca. Elemen Platform ::Collections::Vector orPlatform::Collections::VectorView collection dapat diakses dengan menggunakan iterator atau Vector koleksi ::GetAt dan indeks. Elemen koleksi asosiatif dapat diakses dengan menggunakan Map::Lookup koleksi dan kunci.

Platform::Collections::Map class
Koleksi asosiatif yang dapat dimodifikasi. Elemen peta adalah pasangan kunci-nilai. Mencari kunci untuk mengambil nilai terkaitnya, dan melakukan iterasi melalui semua pasangan kunci-nilai, keduanya didukung.

Map dan MapView di-template pada <K, V, C = std::less<K>>; oleh karena itu, Anda dapat menyesuaikan komparator. Selain itu, Vector dan VectorView di-template <T, E = std::equal_to<T>> sehingga Anda dapat menyesuaikan perilaku IndexOf(). Ini sebagian besar penting untuk Vector dan VectorView struktur nilai. Misalnya, untuk membuat Vektor<Windows::Foundation::D ateTime>, Anda harus menyediakan komparator kustom karena DateTime tidak membebani operator ==.

Platform::Collections::MapView class
Versi baca-saja dari Map.

Platform::Collections::Vector class
Koleksi urutan yang dapat dimodifikasi. Vector<T> mendukung akses acak konstan-waktu dan operasi Amortized-constant-time Append ..

Platform::Collections::VectorView class
Versi baca-saja dari Vector.

Platform::Collections::InputIterator class
Iterator STL yang memenuhi persyaratan iterator input STL.

Platform::Collections::VectorIterator class
Iterator STL yang memenuhi persyaratan iterator akses acak yang dapat diubah STL.

Platform::Collections::VectorViewIterator class
Iterator STL yang memenuhi persyaratan iterator akses acak STL const .

fungsi begin() dan end()

Untuk menyederhanakan penggunaan STL untuk memproses Vectorobjek , , VectorViewMap, MapView, dan arbitrerWindows::Foundation::Collections, C++/CX mendukung kelebihan beban fungsi mulai dan fungsi non-anggota akhir.

Tabel berikut mencantumkan iterator dan fungsi yang tersedia.

Iterator Fungsi
Platform::Collections::VectorIterator<T>

(Penyimpanan internal Windows::Foundation::Collections:: IVector<T> dan int.)
begin/ end(Windows::Foundation::Collections:: IVector<T>)
Platform::Collections::VectorViewIterator<T>

(Penyimpanan internal IVectorView<T>^ dan int.)
mulai/ akhir (IVectorView<T>^)
Platform::Collections::InputIterator<T>

(Penyimpanan internal IIterator<T>^ dan T.)
mulai/ akhir (IIterable<T>)
Platform::Collections::InputIterator<IKeyValuePair<K, V>^>

(Penyimpanan internal IIterator<T>^ dan T.)
mulai/ akhir (IMap<K,V>.
Platform::Collections::InputIterator<IKeyValuePair<K, V>^>

(Penyimpanan internal IIterator<T>^ dan T.)
mulai/ akhir (Windows::Foundation::Collections::IMapView)

Peristiwa perubahan koleksi

Vector dan Map mendukung pengikatan data dalam koleksi XAML dengan menerapkan peristiwa yang terjadi ketika objek koleksi diubah atau direset, atau ketika elemen koleksi apa pun dimasukkan, dihapus, atau diubah. Anda dapat menulis jenis Anda sendiri yang mendukung pengikatan data, meskipun Anda tidak dapat mewarisi dari Map atau Vector karena jenis tersebut disegel.

Delegasi Windows::Foundation::Collections::VectorChangedEventHandler dan Windows::Foundation::Collections::MapChangedEventHandler menentukan tanda tangan untuk penanganan aktivitas untuk peristiwa perubahan koleksi. Kelas enum publik Windows::Foundation::Collections::CollectionChange , dan Platform::Collection::Details::MapChangedEventArgs dan Platform::Collections::Details::VectorChangedEventArgs kelas ref, simpan argumen peristiwa untuk menentukan apa yang menyebabkan peristiwa. Jenis *EventArgs didefinisikan dalam Details namespace layanan karena Anda tidak perlu membuat atau mengonsumsinya secara eksplisit saat Anda menggunakan Map atau Vector.

Baca juga

Sistem Jenis
Referensi Bahasa C++/CX
Referensi Namespace