2017-06-29 21 views
1

我知道如何傳遞一個常量大小的數組作爲參考,但我想知道如何傳遞一個可變大小的數組作爲另一個函數的參考。任何幫助將非常感激。謝謝如何傳遞一個動態分配的「在運行時確定大小」的數組作爲參考?

例如,我有下面的代碼片段:

void y(int (&arr)[n]) //Gives error 
{} 

void x(Node * tree, int n) 
{ 
    int arr[n]; 
    y(arr); 
} 

聽說我們可以templateize功能,使大小模板參數,但我不能這樣做。

+10

不要傳遞數組。傳遞一個'std :: vector'。 –

+6

@Shivam Arora C++不支持可變長度數組。 –

+0

我知道我可以這樣做,但我想在陣列上學習它。無論如何,謝謝。 –

回答

0

此答案用於說明如何在將C++作爲函數參數傳遞給VLA時使用VLA。

在C99中,該語法允許所述陣列的大小作爲參數傳遞給該函數,並使用該函數的參數來聲明VLA的大小:

void y (int n, int (*arr)[n]) 
{} 

void x (int n) 
{ 
    int arr[n]; 
    y(n, &arr); 
} 

C++使用「功能名mangling「作爲將函數接受的參數類型編碼到函數名稱以支持函數重載的技術。但是,在GCC中,由於VLA不是C++支持的功能,因此不存在違規慣例。有人可能會認爲這是一個G ++錯誤(或者VLA擴展的不完整支持),但它就是這樣。爲了模仿通過引用傳遞,接受腐朽的指針作爲參數,並將其轉換爲對VLA的引用。

void y(int n, int *x) 
{ 
    int (&arr)[n] = reinterpret_cast<int (&)[n]>(*x); 
} 

void x(int n) 
{ 
    int arr[n]; 
    y(n, arr); 
} 

我已經驗證過此作品是爲GCC 4.8。

+0

它會工作,如果我把y作爲遞歸函數? –

+0

我沒有看到它無法工作的原因。 – jxh

9

簡單:不要。使用std::arraystd::vector代替:

int get_max(std::vector<int> & vec) {//Could use const& instead, if it doesn't need to be modified 
    int max = std::numeric_limits<int>::min(); 
    for(int & val : vec) {if(max < val) max = val; 
    return max; 
} 

int get_max(std::array<int, 20> & arr) {//Could use const& instead 
    int max = std::numeric_limits<int>::min(); 
    for(int & val : arr) {if(max < val) max = val; 
    return max; 
} 

如果你想這對任何std::array或任何std::vector工作,你可以模板它們像這樣:

template<typename T> 
T get_max(std::vector<T> const& vec) { 
    if(vec.size() == 0) throw std::runtime_error("Vector is empty!"); 
    T const* max = &vec[0]; 
    for(T const& val : vec) if(*max < val) max = &val; 
    return *max; 
} 

template<typename T, size_t N> 
T get_max(std::array<T, N> const& arr) { 
    static_assert(N > 0, "Array is empty!"); 
    T * max = &arr[0]; 
    for(T & val : arr) if(*max < val) max = &val; 
    return *max; 
} 

現在您的代碼應該是這樣的補償:

void y(std::vector<int> & arr) //Can be const& if you don't need to modify it. 
{} 

void x(Node * tree, int n) 
{ 
    std::vector<int> arr(n); //Will initialize n elements to all be 0. 
    y(arr); 
} 
+0

這(最後兩個函數模板)是可怕的使用模板。你沒有理由複製代碼。隱藏模板參數後面的容器。 – rubenvb

+3

@rubenvb這對於需要了解代碼*在分步級別*上進行的新程序員更有用。在更常規的情況下隱藏類型可能是完全合理的,但在回答OP提出的問題時,這並不是有益的。而且,他們並沒有完全相同的事情:後者失敗並出現編譯時錯誤,如果用戶確定他們不需要動態內存,這可能是有益的。 – Xirema

+0

你對「不要」讚不絕口。這就是所有需要說的。 –

0

Xirema已經提到了如何使用來解決這個std::vector/std::array

我不知道你的確切情況,所以只會介紹另一種選擇,儘管事實上,std::vector/std::array是最好的。

指針選項

這裏有相信,中yarrn論點是一致的。並手動處理arr大小。

void y(int * arr, const int n) {} 

void x(Node * tree, int n) { 
    int arr[n]; 
    y(arr, n); 
} 

模板選項

這將工作,howether它將實例對每個新N值2個模板。

template <size_t N> 
void y(int (&arr)[N]) {} 

template <size_t N> 
void x(Node * tree) { 
    int arr[N]; 
    y<N>(arr); 
} 
+0

感謝您的寶貴幫助。 –

+0

模板「選項」不適用於VLA。 – juanchopanza

+0

@juanchopanza:根據你上面的代碼不會工作? –

相關問題