C++ Array 相關筆記

Array 與 Pointer 的關係

  • Array 不是 Pointer 。

Array 是 藉由 pointer 來操作 ,就像是 Iterator 與 STL Container 的關係。

STL Algorithm 可以藉由 Iterator 來操作 STL Container,也可以使用 pointer 來操作 array。 Iterator 就是去模仿 pointer 的行為,像是提領 *i,取下十個位置 i+10、步進 i++、與賦值 *i=element,利用隱性介面來讓 STL Algorithm 可以適用 相同行為 的 Iterator 類操作。

  • Iterator 與 Pointer 在 const 上的相似性 。
    皆指向 int ,沒有 const 相關 限制。
    vector<int>::iterator a;
    int  a;
    
    皆指向 int ,不能藉由 a 去修改被指向的 element 。
    vector<int>::const_iterator a;
    const int  a;
    
    皆指向 int ,可以藉由 a 去修改被指向的 element ,不能修改 pointer 本身,像是無法 a++。
    const vcctor<int>::iterator a;
    int  const a;
    
    皆指向 int ,不能藉由 a 修改被指向的 element ,也不能修改 pointer 本身,像是無法 a++。
    const vector<int>::const_iterator a;
    const int  const a; 
    

Array 的隱性轉型

  • array 做任何加減,都會隱性轉型成 pointer to first element of array type,取值後的 type 就已經不是原本的 array type。

    int a[10];
    auto b = a;  
    auto b = static_cast<int*>(a); // 與第二行等價
    auto c = a + 0;
    auto c = static_cast<int*>(a); // 與第四行等價
    // b  c 都一樣是 pointer to first element to array 型別
    
  • 無法對 array 做 increment(operator++) 與 decrement (operator--)。

    int a[10];
    a++; // compile error
    a--; // compile error
    

    因為 a++ 即為 a = a + 1 ,你無法使 int array type 接收一個 pointer to int type。

  • array 不支援 copy assignment,但可以被 initializer list 初始化。

    int a[10] = { 3, 3, 4, 5, 6, 7, 8}; // 你可以藉由 initializer list 去 initial array , 後面三個元素會被 value-initilization 為 0
    int b[10];
    a = b; // compile error; 你無法對 array 做 assignment
    int c[10] = b; // compile error 你無法藉由 array  initialize 另一個 array 
    

以 Array 進出 Function

  • Function 以 pass by value 傳遞 array 參數 。

以 value 傳遞 array 時,第一維度一律皆自動轉型成 pointer to first element of array type 。

一維陣列
int a[10];
void check1(int a[10]){ cout << typeid(a).name() << endl;}
void check2(int a[]){ cout << typeid(a).name() << endl;}
void check3(int *a){ cout << typeid(a).name() << endl;}
check1(a);
check2(a);
check3(a); 
// 這三種函式是等價的
  • array 參數自動轉型於多維陣列,只限於第一個維度 。

    void check4(int a[10][20][30]){
    cout << typeid(a).name() << endl; // 印出 pi_A20_A30
    }
    

    請記住 array 皆會轉型成 pointer to first element of array type,所以 check4 函式中的 a 的型別,即為一個 pointer to first element of array ,這個 element 的型別是 int[20][30],所以 a 型別是 pointer to int[20][30] type。

  • Function 以 pass by reference 傳遞 array 參數 。

array 會被完整傳遞,不會有任何轉型,因為 reference 只是一種別名。

對 a 修飾成一個 reference
void passArrayByRefernce(int (&a)[10][20]) // 用小括號表示,修飾 a 為一個 reference
{};
  • Function 傳回一個 array reference

可以把 func() 本身當做是上一個例子的 a ,遵照 array 宣告格式:

ArrayElementType Target [ARRAY_SIZE][ARRAY_SIZE]...

如果你要傳回一個 reference ,就是要修飾 function 的本體,把本體包起來,對它使用 & 修飾,再遵照宣告格式,把 function 擺在 Target 的位置上,就會很好思考了。

int (&func())[10][20]  // 回傳一個 Array int [10][20] 的 reference
{...}
cout << typeid(func()).name() << endl; // gcc 印出 A10_A20_i

其他

  • Class 的 array data member

含有 array data member 的 class 在做 copy assignment 時,class A{int a[10];}; A a,b; a = b; 。因為 array 無法被 assignment ,應該是無法做 copy assignment 。不過實際測試過後, C++ 對於 array 這種 built-in type ,似乎會逐一將 array 的 element copy 到 target object 的 array 中。

comments powered by Disqus