2017-05-27 6 views
3

ベクトルの一部を関数に渡し、関数の法線ベクトルとして現れるようにしたいのですが、もっと重要なのは、これがO(1)で一定の時間内に行われることです。私は新しいものを作るためにベクターを反復したくない。実際、次の例では、新しいベクトルのサイズを40に変更します。ベクトルの一部をベクトルとして関数に送ることはできますか?

void func(vector <int> &v){ 

    //calling index 10 to 50 of v 
    func(v[10..50]) 
} 
+3

これは通常、イテレータ範囲で行われています( '' から関数を参照) –

+5

イテレータのペアを送信することが可能です。 – user2079303

+0

2つのイテレータを送信することは、C++で行う慣習的な方法です。 – dasblinkenlight

答えて

5

範囲ベースの関数のパラメータとしてイテレータを使用し、必要な範囲を渡します。関数シグネチャ

void funcWithRange(std::vector<int>::const_iterator first, std::vector<int>::const_iterator last) 

これは、この、そのテンプレートパラメータとしてvectorメンバー型を持つ関数テンプレートことによって一般化、またはさらに別のサポート任意の容器にすることができると

funcWithRange(v.cbegin()+10, v.cbegin()+50); 

なる関数でコードこのタイプの範囲反復。コメントに記されているように、<algorithm>にはこのパターンの多くの例があります。

は、希望の変更サイズを返します。私はあなたが物理的なコピーを作成せずにあなたの要件を満たすことに近づけるとは思わない。

+0

私は知っていますが、1つの引数だけでは可能かどうか疑問に思っていました。 –

+0

私はそれを疑っています。私はいくつかの変換が発生しなければならないだろうと思って、あなたはそれを避けたいと思っていました。 –

+2

@ A.Mashreghiはい、 'std :: pair :: iterator、std :: vector :: iterator>'を使用してください。 –

1

あなたが言う100個の要素

std::vector<int> v(100); 

のベクトルを持っていて、最初の10個の要素とvoid f(std::vector<int> v)を呼び出したい場合は、単に新しいベクターを構築します

f({v.cbegin(), v.cbegin() + 10}); 

としての機能を呼び出します(要素をコピーすることによって)2つのイテレータから新しいベクトルをfに渡します。

+0

このソリューションには欠点があり、元のベクターで機能が機能しなくなります。 –

+0

これは本当に面白いですが、これはベクトルをコピーしますか?私はそれが範囲の長さとは無関係に一定の時間内に働くとは思わない。 –

+1

@ A.Mashreghiはい、これは新しいベクトルを作成するためにコピーしています。新しいベクターが必要な場合は、コピーを避けることはできません。このため、イテレータはC++で多く使われています。要件を再考する必要があります。 – Blastfurnace

1

C++標準に含めるために提案されているこれと類似のものを達成する手段があります。それはspanと呼ばれ、いくつかの点でベクトルのように動作します。

#include <gsl/span> 

void func(gsl::span<int> sp) 
{ 
    for(auto& i: sp) 
     std::cout << i << '\n'; 
} 

int main() 
{ 
    // ... 

    std::vector<int> v(100); 

    // put something in the vector (numbers 0 - 99) 
    std::iota(std::begin(v), std::end(v), 0); 

    // wrap the container in a span 
    auto sp = gsl::make_span(v); 

    // send parts of it to functions 
    func(sp.subspan(10, 50)); 
} 

spanの実装では、ここで見つけることができます:https://github.com/Microsoft/GSL

これはビャーネ・ストロヴストルップとハーブサッターによってベストプラクティスガイドで連続したコンテナを渡すの推奨される方法です。

ガイドラインはここで見つけることができます:CppCoreGuidelines.md

+0

2つのイテレータの 'std :: pair 'との違いは何ですか? –

+0

@πάνταῥε '' span'はチェックされた境界であり、 'API'はより頑強であると考えられ、範囲外の範囲を得るのを難しくしています。範囲外の 'v.begin()+ 50'を実行すると、静的に未定義の動作を行う例外が発生しません。しかし 'sp.subspan(0、50)'がチェックされます。 – Galik

+0

@Galik funcに渡されたサブスパンを操作すると、spの元の値が変更されますか?私はこれが原本へのコピーか参照ですか? –

関連する問題