Share via


Array 和 WriteOnlyArray (C++/CX)

您可以自由使用一般 C 樣式陣列或 std::array C++/CX 程式中(雖然 std::vector 通常是較佳的選擇),但在中繼資料中發佈的任何 API 中,您必須根據使用方式,將 C 樣式陣列或向量 Platform::Array 轉換成 或 Platform::WriteOnlyArray 類型。 此 Platform::Array 類型既沒有效率,也不如強大 std::vector ,因此作為一般指導方針,您應該避免在內部程式碼中使用,在陣列元素上執行大量作業。

下列陣列類型可以透過 ABI 傳遞:

  1. const Platform::Array^

  2. Platform::Array^*

  3. Platform::WriteOnlyArray

  4. 傳回值 Platform::Array^

您可以使用這些陣列類型來實作Windows 執行階段所定義的三種陣列模式。

PassArray
當呼叫端將陣列傳遞給方法時使用。 C++ 輸入參數類型為 constPlatform::Array< T。 >

FillArray
當呼叫端傳遞陣列供方法填入時使用。 C++ 輸入參數類型為 Platform::WriteOnlyArray< T > 。

ReceiveArray
當呼叫端接收方法所配置的陣列時使用。 在 C++/CX 中,您可以傳回值 Array^ 傳回陣列,也可以傳回做為 Array^ 類型的 out 參數。

PassArray 模式

當用戶端程式代碼將陣列傳遞至 C++ 方法,而 方法不會修改它時,方法會將陣列接受為 const Array^ 。 在Windows 執行階段應用程式二進位介面 (ABI) 層級,這稱為 PassArray 。 下一個範例顯示如何將 JavaScript 中配置的陣列傳遞至讀取此陣列的 C++ 函式。

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

下列程式碼片段示範 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;
}

ReceiveArray 模式

在 ReceiveArray 模式中 ,用戶端程式代碼會宣告陣列,並將它傳遞給配置記憶體並初始化它的方法。 C++ 輸入參數類型是指標對帽子: Array<T>^* 。 下列範例顯示如何在 JavaScript 中宣告陣列物件,並將它傳遞至 C++ 函式,此函式會配置記憶體、初始化元素,然後將它傳回至 JavaScript。 JavaScript 將配置的陣列視為傳回值,但 C++ 函式將它視為 out 參數。

//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] + " ";
    }
}

下列程式碼片段示範實作 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;
}

填入陣列

當您想要在呼叫端配置陣列,並在被呼叫端初始化或修改它時,請使用 WriteOnlyArray。 下一個範例顯示如何實作使用 WriteOnlyArray 的 C++ 函式,以及從 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] + " ";
    }
}

下列程式碼片段示範如何實作 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;
    }   
}

陣列轉換

此範例示範如何使用 Platform::Array 來建構其他類型的集合:

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

下一個範例示範如何從 C 樣式陣列建構 Platform::Array ,並從公用方法傳回它。

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

不規則陣列

Windows 執行階段類型系統不支援不規則陣列的概念,因此您也就不能使用 IVector<Platform::Array<T>> 做為公用方法的傳回值或方法參數。 若要跨 ABI 傳遞不規則陣列或一組序列中的某個序列,請使用 IVector<IVector<T>^>

使用 ArrayReference 可避免複製資料

在某些將資料傳遞至 Platform::Array ABI 的案例中,您最終想要在 C 樣式陣列中處理該資料以提高效率,您可以使用 Platform::ArrayReference 來避免額外的複製作業。 當您將 當做引數傳遞 Platform::ArrayReference 至採用 Platform::Array 的參數時, ArrayReference 會將資料直接儲存至您指定的 C 樣式陣列。 請注意, ArrayReference 不會鎖定來源資料,因此如果在呼叫完成之前修改或刪除另一個執行緒上的資料,結果會是未定義的。

下列程式碼片段示範如何將作業 Platform::Array 的結果 DataReader 複製到 (一般模式),以及如何替代 ArrayReference 將資料直接複製到 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) );
    }
};

避免將陣列公開為屬性

一般而言,您應該避免將 Platform::Array 類型公開為 ref 類別中的屬性,因為即使用戶端程式碼只嘗試存取單一元素,也會傳回整個陣列。 當您需要將序列容器公開為公用 ref 類別中的屬性時, Windows::Foundation::IVector 是較佳的選擇。 在私人或內部 API 中,請考慮使用標準 C++ 容器,例如 std::vector

另請參閱

類型系統
C++/CX 語言參考
命名空間參考