1. 程式人生 > >從函式返回陣列

從函式返回陣列

 

摘要:C++中存在兩種引數傳遞方式,但語言存在上的陣列與一般結構不同,它會在引數傳遞過程轉化為指標,這是從C中繼承下來。從而使得在函式中返回陣列很困難。本文講述幾種可能的方法。

問題

我們在函式裡面準備一個數組,或者說一組資料,現在想把這組資料返回到呼叫環境中去,就好比如下的程式碼:

something fun()
{
        int array[3]={ 1, 3, 4};

        return something;
}

int main()
{
        something = fun();
       
        return 0;
}

可以說上面的程式碼看上去很優美,可是在C++如何實現那個fun函式呢?那個something具體是什麼內容?

解答

非常遺憾,我沒有辦法在語言內建陣列上實現如此優美的程式碼;如果我們使用使用者陣列如類似天vetor物件時,我可以寫出這麼優美的程式碼,但是在當前的C++標準(C++03)下它效率很低,在下一代標準中這一點可以實現。

讓我們分析一下,要實現傳遞陣列需要哪些準備:

  • 首先資料儲存的物件不能是自動生命期的,因為這樣的話函式結束時,它會被銷燬,所以它只能是靜態生命期的或自由生命期的。
  • 通過上面的分析我們產生出兩種可能的解決方案:一是返回一個靜態陣列,二是返回一個動態陣列,總之不能返回自動陣列。

返回靜態陣列的方案大體程式碼如下:

int * fun()
{
        static int array[3]
={ 1, 3, 4};
       
        return array;
}

這個方案有幾個缺點:

  • array的所有權是fun函式的,這個函式是全域性的,所以array也是全域性的,這意味著array是全域性共享的,此時在多執行緒中必然不安全,甚至是災難。不可行。
  • 呼叫環境無法確定array的性質,甚至沒有可行的辦法知道array的大小,所以就算在單執行緒中也不具有十分安全。
  • 使用者無法更改array的性質,使得這樣的函式使用的情況非常有限,不可能大面積使用。

之前的C中常有這種方案的出現,但C++不贊成這樣使用,因為我們在C++似乎有一個比這個強一點的方案。

返回動態陣列的方案要比返回靜態陣列的方案靈活多變,但也不是很完美,等到C++0x或者C++1x的時候可以改變這個情況。我們給出兩個可能的示例程式碼:

int* fun(size_t n)
{
        int* p = new int[n];
        //do something
       
        return p;
       
        //這個方案最大缺點就是使用者需要手工釋放記憶體
        //這在C++社群裡不被支援,這些記憶體管理應該更自動化
}
//可能考慮使用智慧指標
smart_ptr fun(size_t n)
{
        smart_ptr<int> p(new int[n]);
       
        //do something
       
        return p;
       
        //這個方案似乎是最好的,它是效率與可用性的折中
        //還有一個思路就是把整個陣列都複製出去,它是最直觀的,但是效率很差
        //效率差在C++下一代標準中可以得到解決,所謂“右值引用”就是用來解決它的
        //C++下一代標準叫做C++0x或C++1x,本站有相關內容
}

總之在現在有C++標準裡沒有一個高效的直觀的方案來解決陣列返回問題,人們往往採用其中比較折中的方案。