[轉]數組引用:C++ 數組做參數 深入分析

來源:互聯網
上載者:User

標籤:

"數組引用"以避免"數組降階"(本文曾貼於VCKBASE\C++論壇)

受[hpho]的一段模板函數的啟發,特寫此文,如有雷同,實在遺憾。
數組降階是個討厭的事,這在C語言中是個無法解決的問題,先看一段代碼,瞭解什麼是"數組降階"

#include <IOSTREAM>
using namespace std;

void Test( char array[20] )
{
    cout << sizeof(array) << endl; // 輸出 4
}

int main( void )
{
    char array[20] = { 0 };
    cout << sizeof(array) << endl; // 輸出 20
    Test( array );
}

為什麼同樣申明的array一個輸出20一個輸出4?這是因為void Test( char array[20] )中的array被降階處理了,void Test( char array[20] )等同於void Test( char array[] ),也等同於void Test( char* const array ),如果你BT(開玩笑),它也等同於void Test( char array[999] )。
就是說
void Test( char array[20] )
{
    cout << sizeof(array) << endl;
}
被降成
void Test( char* const array )
{
    cout << sizeof(array) << endl; // 既然是char*,當然輸出4
}
這樣一來問題大了,你完全可以定義一個不足20個元素的數組,然後傳給Test,坐等程式崩潰。在一些要求較高的場合就不能使用數組做參數,真TMD心有不甘。

那麼在C語言中怎樣解決這個問題?
沒辦法,應該說沒有好辦法。a:做個結構,其中僅一個char array[20],然後用這個結構指標代替char array[20]。可見這是個很繁瑣的辦法,且不直觀;b:在Test內部使用_msize來計算array長度。這更不行,首先它使得錯誤的發現被延遲到運行期,而不是編譯期,其次_msize長度/元素大小>=array長度,也就是說就是new char[19]和new array[20]分配的大小是一樣的,這樣一來,雖不至於導致程式崩潰,但運算結果卻不正確。

感謝[hpho],受其啟發,C++中有C所沒有的"引用",但數組引用是怎樣申明的呢?經過幾番實驗,Look

#include <IOSTREAM>
using namespace std;

void Test( char (&array)[20] ) // 是不是很像 char *p[20] 和 char (*p)[20] 的區別?
{
    cout << sizeof(array) << endl;
}

int main( void )
{
    char array[20] = { 0 };
    cout << sizeof(array) << endl;
    Test( array );
}

在 C++中,數組永遠不會按值傳遞,它是傳遞第一個元素,準確地說是第 0個 的指標。

例如,如下聲明 :
void putValues( int[ 10 ] );
被編譯器視為 
void putValues( int* );
數組的長度與參數聲明無關,因此,下列三個聲明是等價的:
// 三個等價的 putValues()聲明
void putValues( int* );
void putValues( int[] );
void putValues( int[ 10 ] );

因為數組被傳遞為指標 所以這對程式員有兩個含義:

1. 在被調函數內對參數數組的改變將被應用到數組實參上而不是本地拷貝上,當用作實參的數組必須保持不變時,程式員需要保留原始數組的拷貝函數可以通過把參數型別宣告為 const 來表明不希望改變數組元素。
void putValues( const int[ 10 ] );

2.  數組長度不是參數類型的一部分,函數不知道傳遞給它的數組的實際長度,編澤器也不知道,當編譯器對實參類型進行參數類型檢查時,並不檢查數組的長度。例如:
void putValues( int[ 10 ] ); // 視為 int*
int main() {
int i, j[ 2 ];
putValues( &i ); // ok: &i 是 int*; 潛在的運行錯誤
putValues( j ); // ok: j 被轉換成第 0 個元素的指標
// 實參類型為 int*: 潛在的運行錯誤
return 0;
}

參數的類型檢查只能保證putValues()的兩次調用都提供了int*型的實參,類型檢查不能檢驗實參是一個 10元素的數組 。習慣上, C風格字串是字元的數組,它用一個Null 字元編碼作為結尾。但是所有其他類型,包括希望處理內含Null 字元的字元數組必須以某種方式在向函數傳遞實參時使其知道它的長度。

一種常見的機制是提供一個含有數組長度的額外參數。例如:
void putValues( int[], int size );
int main() {
       int i, j[ 2 ];
       putValues( &i, 1 );
       putValues( j, 2 );
       return 0;
}

另外一種機制是將參數聲明為數組的引用

當參數是一個數群組類型的引用時,數組長度成為參數和實參類型的一部分,編譯器檢查數組實參的長度與在函數參數類型中指定的長度是否匹配。 
// 參數為 10 個 int 的數組
// parameter is a reference to an array of 10 ints
void putValues( int (&arr)[10] );//不能寫成&arr[10],因為下標操作符的優先順序較高
int main() {
       int i, j[ 2 ];
       putValues( i ); // 錯誤: 實參不是 10 個 int 的數組
       putValues( j ); // 錯誤: 實參不是 10 個 int 的數組
       return 0;
}

[轉]數組引用:C++ 數組做參數 深入分析

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.