共用方式為


Array 和 WriteOnlyArray (C++/CX)

您可以在 C++/CX 程式中任意使用標準 C-Style 陣列或 std::array (雖然 std::vector 通常是比較好的選擇),但若是在中繼資料中所發行的任何 API 中,您必須根據 C-Style 陣列或向量的用途,將其轉換為 Platform::ArrayPlatform::WriteOnlyArray 類型。 Platform::Array 類型的效率及功能都不如 std::vector,因此一般來說,您應該避免在對陣列元素執行許多作業的內部程式碼中使用此類型。

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

  1. const Platform::Array^

  2. Platform::Array^*

  3. Platform::WriteOnlyArray

  4. 傳回 Platform::Array^ 的值

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

PassArray
當呼叫端將陣列傳遞給方法時使用。 C++ 輸入參數類型為 const Platform::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++ 輸入參數類型為 Hat 指標: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-Style 陣列建構 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 可避免複製資料

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

下列程式碼片段示範如何將 DataReader 作業的結果複製到 Platform::Array 中 (一般模式),以及如何接著替代 ArrayReference,將資料直接複製到 C-Style 陣列中:

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 會是較佳選擇。 在私用或內部應用程式開發介面中 (不會發行到中繼資料),請考慮使用 Standard C++ 容器,例如 std::vector

另請參閱

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