2017-06-29 7 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

この答えは、VLAを関数パラメータとして渡すときに、C++で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::arrayまたはstd::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

これは(最後の2つの関数テンプレート)テンプレートのひどい使い方です。あなたは何の理由もなくコードを複製しています。テンプレートパラメータの背後にあるコンテナを非表示にします。 – rubenvb

+3

@rubenvbこれは、ステップバイステップのレベルで*何をしているのかを理解する必要のある、より新しいプログラマーにとってはより役に立ちます。より一般的な状況では、タイプを隠すことは完全に合理的かもしれませんが、OPが出したような質問に答えるときは有益ではありません。また、同じことをしているわけではありません。後者はコンパイル時にエラーが発生し、ユーザーが動的メモリを必要としないと確信できれば有益です。 – Xirema

+0

あなたは「しない」のためのアップコートを手に入れます。それは言われるべきことのすべてです。 –

0

Xiremaは、すでに使用して、これを解決する方法を述べたstd::vector/std::array

私はあなたの大文字小文字を正確には分からないので、別のオプションを説明するだけで、実際には/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:あなたによれば、上記のコードは動作しませんか? –

関連する問題