首頁 > 程式設計 > [C/C++] 陣列當作參數傳遞的函式實做方法

[C/C++] 陣列當作參數傳遞的函式實做方法

在網路上無意間看到(原創) 如何使用function template傳遞array? (C/C++) (template)的幾篇文章後,我翻開我那塵封已久的C++ Primer 4/e,將有關陣列當做參數傳遞到函數的實作方法,整個初階到較為高階的做法,整理過後如下:
一般來說,我們若要讓函數傳遞陣列時,會寫以下:

/*
*  @Function: void fnPrintArray(int arr[10])
*  @Brief: Print the array content.
*  @Input: int arr[10]
*  @Output: array content.
*/
void fnPrintArray(int arr[10])
{
    for(size_t i=0;i<10;++i)
    {
        std::cout << i << " " << std::endl;
    }
}

但是此函式主要有兩個問題:
1. 若傳入的陣列只有包含3個元素時,會有out of range的問題。
2. 若傳入的陣列長度超過10,則無法完整印出該陣列內容。
針對上述問題的解法,C++ 在訂出reference這個概念後,array也可以用以下來代替:

/*
*  @Function: void fnPrintArray(int arr[10])
*  @Brief: Print the array content , and the input is by reference.
*  @Input: int arr[10]
*  @Output: array content.
*/
void fnPrintArray(int (&arr)[10])
{
    for(size_t i=0;i<10;++i)
    {
        std::cout << i << " " << std::endl;
    } 
}

此一reference的技巧,在於限定傳入的陣列大小只有10,降低了使用上的風險。
其中,傳入的參數int (&arr)[10] 表示傳入一個reference,其reference到具有10個int元素的陣列
若不加入括號的話:int &arr[10]表示傳入一個長度為10的陣列,每一個元素型態皆為int &
不過,如此作法卻大大降低了可用性。

因此,如何管理好陣列大小,便成為一個令人頭痛的問題!根據C/C++ Primer 4/e 提出常用的解法有三:
1. 函式另外傳入兩個指標,分別指向陣列開頭以及陣列結尾。
2. 如1.所述,不同的是,將原本指到陣列結尾的指標轉而指向陣列結尾的下一個。
3. 函式須指明給定陣列的明確長度。
但是,此方法在實用性上略顯不足,難道沒有一個更有效的方法嗎?

我們可以利用C++的template來幫我們實現這個方案。

#include <iostream>
using namespace std;
/*
* @Function:
        template<typename T,size_t N>
        void fnChange(T (&arr)[N])
* @Brief: Let each element of array increase by one.
* @Input: 1D array
* @Output: The array whose elements all increase by 1
*/
template<typename T,size_t N>
void fnChange(T (&arr)[N])
{
    for(size_t i=0;i<N;++i)
        arr[i]+=1;
}
int main(int argc, char * argv[])
{
    int arr1D[3]={1,2,3};  // Create 1D array.
    int arr2D[3][2] = { {1,2},{3,4},{5,6}}; // Create 2D array.
    // Show the initialized result.
    for(int i=0;i<3;++i)
    {
        cout << arr1D[i] << endl;
    }
    fnChange(arr1D);
    // Show the result.
    for(int i=0;i<3;++i)
    {
        cout << arr1D[i] << endl;
    }
    return 0;
}

上述程式碼,利用樣板特化的技巧,讓函式不用帶入陣列大小,便可透過樣板參數幫我們自動得知陣列大小,以利函式功能的撰寫。
因此,舉一反三,我們可以藉此程式碼推廣至二維陣列,範例程式碼如下:

#include <iostream>
using namespace std;
/*
* @Function:
        template<typename T,size_t M,size_t N>
        void fnPrint2DArray(T (&arr)[M][N])
* @Brief: Print the  content of 2D Array.
* @Input: 2D array.
* @Output: None.
*/
template<typename T,size_t M,size_t N>
void fnPrint2DArray(T (&arr)[M][N])
{
    for(size_t i=0;i<M;++i)
    {
        for(size_t j=0; j<N; ++j)
        {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }
}
int main(int argc, char * argv[])
{
    int arr2D[3][2] = { {1,2},{3,4},{5,6}}; // Create 2D array.
    // Print 2D array.
    fnPrint2DArray(arr2D);
    return 0;
}

因此,對於陣列的參數傳遞,我們可以利用樣板的功能來幫我順利達成。似乎一切在這邊有了完整的解答。:)
Reference
C++ Primer 中文版 4/e page. 110 , 240~241, 632~633.
(原創) array傳進function該怎麼寫才好? (C/C++) (C) 推薦閱讀!

分類:程式設計 標籤:,
  1. 十二月 19, 2014 at 8:55 下午

    這裡有一個問題 如果我在函數中改變陣列內的值 離開函數 陣列中的值有沒有改變

  1. No trackbacks yet.

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 變更 )

Twitter picture

You are commenting using your Twitter account. Log Out / 變更 )

Facebook照片

You are commenting using your Facebook account. Log Out / 變更 )

Google+ photo

You are commenting using your Google+ account. Log Out / 變更 )

連結到 %s

%d 位部落客按了讚: