Array dan WriteOnlyArray (C++/CX)

Anda dapat dengan bebas menggunakan array gaya C reguler atau std::array dalam program C++/CX (meskipun std::vector sering kali merupakan pilihan yang lebih baik), tetapi dalam API apa pun yang diterbitkan dalam metadata, Anda harus mengonversi array gaya C atau vektor ke Platform::Array atau Platform::WriteOnlyArray jenis tergantung pada cara penggunaannya. Jenisnya Platform::Array tidak seefisien atau sekuat std::vector, sehingga sebagai pedoman umum Anda harus menghindari penggunaannya dalam kode internal yang melakukan banyak operasi pada elemen array.

Jenis array berikut dapat diteruskan di seluruh ABI:

  1. const Platform::Array^

  2. Platform::Array^*

  3. Platform::WriteOnlyArray

  4. nilai pengembalian dari Platform::Array^

Anda menggunakan jenis array ini untuk mengimplementasikan tiga jenis pola array yang ditentukan oleh Windows Runtime.

PassArray
Digunakan saat penelepon meneruskan array ke metode . Jenis parameter input C++ adalah constPlatform::Array<T.>

FillArray
Digunakan saat penelepon meneruskan array untuk mengisi metode. Jenis parameter input C++ adalah Platform::WriteOnlyArray<T>.

ReceiveArray
Digunakan saat pemanggil menerima array yang dialokasikan metode. Di C++/CX Anda dapat mengembalikan array dalam nilai pengembalian sebagai Array^ atau Anda dapat mengembalikannya sebagai parameter keluar sebagai jenis Array^*.

Pola PassArray

Ketika kode klien meneruskan array ke metode C++ dan metode tidak memodifikasinya, metode menerima array sebagai const Array^. Pada tingkat antarmuka biner aplikasi Windows Runtime (ABI), ini dikenal sebagai PassArray. Contoh berikutnya menunjukkan cara meneruskan array yang dialokasikan di JavaScript ke fungsi C++ yang dibaca darinya.

//JavaScript
function button2_click() {
    var obj = new JS-Array.Class1();
    var a = new Array(100);
    for (i = 0; i < 100; i++) {
        a[i] = i;
    }
    // Notice that method names are camelCased in JavaScript.
    var sum = obj.passArrayForReading(a);
    document.getElementById('results').innerText
        = "The sum of all the numbers is " + sum;
}

Cuplikan berikut menunjukkan metode C++:

double Class1::PassArrayForReading(const Array<double>^ arr)
{
    double sum = 0;
    for(unsigned int i = 0 ; i < arr->Length; i++)
    {
        sum += arr[i];
    }
    return sum;
}

Pola ReceiveArray

Dalam pola ReceiveArray, kode klien mendeklarasikan array dan meneruskannya ke metode yang mengalokasikan memori untuk itu dan menginisialisasinya. Jenis parameter input C++ adalah pointer-to-hat: Array<T>^*. Contoh berikut menunjukkan cara mendeklarasikan objek array di JavaScript, dan meneruskannya ke fungsi C++ yang mengalokasikan memori, menginisialisasi elemen, dan mengembalikannya ke JavaScript. JavaScript memperlakukan array yang dialokasikan sebagai nilai pengembalian, tetapi fungsi C++ memperlakukannya sebagai parameter keluar.

//JavaScript
function button3_click() {
    var obj = new JS-Array.Class1();

    // Remember to use camelCase for the function name.
    var array2 = obj.calleeAllocatedDemo2();
    for (j = 0; j < array2.length; j++) {
        document.getElementById('results').innerText += array2[j] + " ";
    }
}

Cuplikan berikut menunjukkan dua cara untuk mengimplementasikan metode C++:


// Return array as out parameter...
void Class1::CalleeAllocatedDemo(Array<int>^* arr)
{
    auto temp = ref new Array<int>(10);
    for(unsigned int i = 0; i < temp->Length; i++)
    {
        temp[i] = i;
    }

    *arr = temp;
}

// ...or return array as return value:
Array<int>^ Class1::CalleeAllocatedDemo2()
{
    auto temp = ref new Array<int>(10);    
    for(unsigned int i = 0; i < temp->Length; i++)
    {
        temp[i] = i;
    }

    return temp;
}

Isi array

Saat Anda ingin mengalokasikan array di pemanggil, dan menginisialisasi atau memodifikasinya di penerima panggilan, gunakan WriteOnlyArray. Contoh berikutnya menunjukkan cara mengimplementasikan fungsi C++ yang menggunakan WriteOnlyArray dan memanggilnya dari JavaScript.

// JavaScript
function button4_click() {
    var obj = new JS-Array.Class1();
    //Allocate the array.
    var a = new Array(10);

    //Pass the array to C++.
    obj.callerAllocatedDemo(a);

    var results = document.getElementById('results');
    // Display the modified contents.
    for (i = 0; i < 10; i++) {
        document.getElementById('results').innerText += a[i] + " ";
    }
}

Cuplikan berikut menunjukkan cara menerapkan metode C++:

void Class1::CallerAllocatedDemo(Platform::WriteOnlyArray<int>^ arr)
{
    // You can write to the elements directly.
    for(unsigned int i = 0; i < arr->Length; i++)
    {
        arr[i] = i;
    }   
}

Konversi array

Contoh ini menunjukkan cara menggunakan Platform::Array untuk membuat jenis koleksi lainnya:

#include <vector>
#include <collection.h>
using namespace Platform;
using namespace std;
using namespace Platform::Collections;

void ArrayConversions(const Array<int>^ arr)
{
    // Construct an Array from another Array.
    Platform::Array<int>^ newArr = ref new Platform::Array<int>(arr);

    // Construct a Vector from an Array
    auto v = ref new Platform::Collections::Vector<int>(arr); 

    // Construct a std::vector. Two options.
    vector<int> v1(begin(arr), end(arr));
    vector<int> v2(arr->begin(), arr->end());

    // Initialize a vector one element at a time.
    // using a range for loop. Not as efficient as using begin/end.
    vector<int> v3;
    for(int i : arr)
    {
        v3.push_back(i);
    }   
}

Contoh berikutnya menunjukkan cara membuat Platform::Array dari array gaya C dan mengembalikannya dari metode publik.

Array<int>^ GetNums()
{
    int nums[] = {0,1,2,3,4};
    //Use nums internally....

    // Convert to Platform::Array and return to caller.
    return ref new Array<int>(nums, 5);
}

Array Bergerigi

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

Menggunakan ArrayReference untuk menghindari penyalinan data

Dalam beberapa skenario di mana data diteruskan di seluruh ABI ke dalam Platform::Array, dan Anda pada akhirnya ingin memproses data tersebut dalam array gaya C untuk efisiensi, Anda dapat menggunakan Platform::ArrayReference untuk menghindari operasi penyalinan tambahan. Saat Anda meneruskan Platform::ArrayReference sebagai argumen ke parameter yang mengambil Platform::Array, ArrayReference akan menyimpan data langsung ke array gaya C yang Anda tentukan. Ketahuilah bahwa ArrayReference tidak memiliki kunci pada data sumber, jadi jika data dimodifikasi atau dihapus pada utas lain sebelum panggilan selesai, hasilnya tidak akan ditentukan.

Cuplikan kode berikut menunjukkan cara menyalin hasil DataReader operasi ke dalam Platform::Array (pola biasa), lalu cara mengganti ArrayReference untuk menyalin data langsung ke array gaya C:

public ref class TestReferenceArray sealed
{
public:

    // Assume dr is already initialized with a stream
    void GetArray(Windows::Storage::Streams::DataReader^ dr, int numBytesRemaining)
    {
        // Copy into Platform::Array
        auto bytes = ref new Platform::Array<unsigned char>(numBytesRemaining);            

        // Fill an Array.
        dr->ReadBytes(bytes);

        // Fill a C-style array
        uint8 data[1024];
        dr->ReadBytes( Platform::ArrayReference<uint8>(data, 1024) );
    }
};

Hindari mengekspos Array sebagai properti

Secara umum, Anda harus menghindari mengekspos Platform::Array jenis sebagai properti di kelas ref karena seluruh array dikembalikan bahkan ketika kode klien hanya mencoba mengakses satu elemen. Ketika Anda perlu mengekspos kontainer urutan sebagai properti di kelas ref publik, Windows::Foundation::IVector adalah pilihan yang lebih baik. Dalam API privat atau internal (yang tidak diterbitkan ke metadata), pertimbangkan untuk menggunakan kontainer C++ standar seperti std::vector.

Baca juga

Sistem Jenis
Referensi Bahasa C++/CX
Referensi Namespace