2017-02-02 5 views
0

は、のような何かをすることは簡単です:std :: vectorの名前をC型の配列名のように扱うにはどうしたらいいですか? Cで

int foo (int arr[], int size) { 

    // Do some stuff. 

    // Recur ignoring half of the input array. 
    return foo (arr + size/2, size/2); 
} 

私はC言語で、配列の名前は基本的にメモリ内の連続ブロックへのポインタで、基本的なので、我々はそれを行うことが可能であることを知っていますポインタの算術演算はうまく動作します。

私の質問は、C++ベクタまたは配列コンテナでこのような便利さを達成するにはどうすればよいですか?基本的にそれをやる代わりのトリックはありますか?

私が知っているから、これはまったく機能しません。

int foo (vector<int>& arr, int size) { 

    // Do some stuff. 

    // Recur ignoring half of the input array. 
    return foo (arr + size/2, size/2); 
} 
+3

必要なチャンクの開始と終了のイテレーターを渡す –

+0

@YuriyIvaskevychはい、それは可能ですが、機能の署名を変更する自由がない場合はどうなりますか? – Duh

+0

'std :: vector'をお持ちの場合、サイズを渡す必要はありません。また、イテレータの範囲がある場合は、それを計算できます。 –

答えて

1

あなたが機能に対応しているベクトルのdata()size()プロパティ、渡すことができるよりも、あなたは関数のシグネチャを変更できない場合:

foo(v.data(), v.size()); 
+0

あなたの答えは私が質問した正確な質問に対応しています。しかし、[vector :: data](http://www.cplusplus.com/reference/vector/vector/data/)が使用されているメモリブロックへのポインタを返すため、関数シグニチャを変更する必要がありますベクトルによって。 – Duh

+0

する必要はありません。 'std :: vector :: data()'と 'int []'は互換性があります。配列が関数に到達したときにポインタが壊れていることに注意してください。それは私のためにうまくコンパイルされます。 –

+0

あなたは気付かなかったかもしれません。 'arr'は' int [] 'のようにint配列ではないベクトルとして宣言されます。また、私は同じ関数を繰り返しているので、あなたのコメントは私を混乱させます。 'arr'はベクトルです:: :: data()'を使用しますが、あなたの最後のコメントから 'arr' 'int []'とタイプしてください。明確にすることはできますか? – Duh

1

C++ソリューションは、使用しているオブジェクトの観点で考えることです。 vector

だから、あなたは単にイテレータを使用してのようなものを行うことができます。つまり

arr.begin() 
arr.begin()+(size/2) 

:代わりに、対応するC++の概念を使用し、C++にCの概念を押します。

この場合、iteratorsを使用して、アレイの「パーツ」を外部に「利用可能」にすることができます。

0

あなたはstd::vector<int>で作業しているので、明白な答えを機能をまったく変更しないことです。

単に別の言葉で表してください。

foo(&some_vector[0], some_vector.size()); // assume some_vector is not const 

これはあなたのCスタイルfoo()への最初の要素とsome_vectorのサイズへのポインタを渡します。 std::vectorの要素は連続していることが保証されているので、これは要求どおりに動作します。

個人的には、私はそれをしません。私はイテレータを使用します。

#include <iterator> 

int foo (std::vector<int>::iterator begin, std::vector<int>::iterator end) 
{ 

    // Do some stuff. 

    // Recur ignoring half of the input array. 

    std::advance(begin, std::distance(begin, end)/2); 
    return foo (begin, end); 
} 

// to call it 

foo(some_vector.begin(), some_vector.end()); 

関数内で無限再帰を避けるためには、明らかにいくつかのロジックが必要です。しかし、それはあなたが始まった機能にも当てはまります。

テンプレートが

それはイテレータ(またはどこから来るの容器の種類)についてのハードコード仮定する必要がないため、より簡単でより一般的なの両方を作った私にはこれを許可
#include <iterator> 

template<class Iterator> 
int foo (Iterator begin, Iterator end) 
{ 

    // Do some stuff. 

    // Recur ignoring half of the input array. 

    std::advance(begin, std::distance(begin, end)/2); 
    return foo (begin, end); 
} 

// call like before 

std::advance()の要件そして、std::distance()は非常に最小です - 本質的にイテレータは標準呼び出しのものです入力イテレータ(イテレータが指す各値が一度だけ読み込まれ、イテレータがインクリメントされる順次入力操作で使用できることを意味します) 。あなたの "Do stuff"コードはより制限的な要件を導入するかもしれません。

関連する問題