39

ベクトル内の各要素にアクセスし、その要素がどのインデックスにあるかを知る必要があります。

これまでのところ、2つの方法を考え出すことができました

 for (iterator it= aVector.begin(), int index= 0; it!= aVector.end(); ++it, ++index)

型署名を残します。また、私は自動を使用できないようです

 for (int index = 0; index < aVector.size(); ++index)
{
    // access using []
}

どちらがより効率的ですか、それともこれを行うためのより良い方法がありますか?

4

8 に答える 8

24

ベクトルまたはその他のランダムアクセスコンテナの場合、ほとんど違いはありません。読みやすく、更新するループ変数が1つしかないため、おそらくわずかに高速であるため、おそらく2番目を選択します。別の選択肢は次のとおりです。

for (auto it = aVector.begin(); it != aVector.end(); ++it) {
    int index = std::distance(aVector.begin(), it);
}

非ランダムアクセスコンテナの場合、[]利用できず、std::distance非効率的です。その場合、インデックスが必要な場合は、最初のメソッドの方が適しています(ただし、for-initialiserで2つの異なる型の変数を宣言しないように修正する必要があります)。

于 2012-09-19T13:14:23.567 に答える
11

答えは、「要素がどのインデックスにあるかを知っている」という質問にあります。

それで -

for (int index = 0; index < aVector.size(); ++index)
{
    // access using []
}

パフォーマンスに関しては同じです(ただし、いつでも自分のプロファイルを作成できます)。

于 2012-09-19T13:10:26.903 に答える
4

別の方法。

int count = 0;
for (auto& it : aVector) {
   count++;
}
于 2021-03-15T11:30:32.230 に答える
3

Boost.Rangeのアダプターを使用できます。これは、現在のインデックス(duh)を返すメソッドでindexed範囲のイテレーターを拡張します。index

#include <boost/range/adaptor/indexed.hpp>

// ...
auto&& r = vec | boost::adaptors::indexed(0);
for(auto it(begin(r)), ite(end(r)); it != ite; ++it)
  std::cout << it.index() << ": " << *it << "\n";

残念ながら、はイテレータのメソッドの一部であるため、これは、要素へのアクセスのみを許可indexする新しい範囲ベースのforループまたはを使用できないことを意味します。BOOST_FOREACHこれは、疑わしい値のかなり定型的な回避策です。

// note: likely contains typos or bugs
#include <boost/range/adaptors.hpp>

template<class IndexIt>
auto pair_index_value(IndexIt it)
    -> std::pair<std::size_t, decltype(*it)>
{
  return std::pair<std::size_t, decltype(*it)>(it.index(), *it);
}

// ...
using namespace boost::adaptors;

auto&& ir = vec | indexed; // because screw you Boost.Range
for(auto&& elem : boost::counting_range(ir.begin(), ir.end()) | transformed(pair_index_value))
  std::cout << elem.first << ": " << elem.second << "\n";
于 2012-09-19T14:05:55.460 に答える
3

これは、Boost.Iteratorライブラリを使用したソリューションzip_iteratorです。これはおそらくユースケースにとってはやり過ぎですが、任意の範囲(ベクトルだけでなく)で動作し、標準アルゴリズムのイテレーターベースの設計にうまく適合するという利点があるため、ここに投稿します。counting_iterator

#include <boost/iterator/counting_iterator.hpp>
#include <boost/iterator/zip_iterator.hpp>

#include <algorithm>
#include <iostream>
#include <list>

int main()
{
    typedef std::list<int> container;

    typedef boost::tuple<
        container::iterator,
        boost::counting_iterator<container::size_type>
    > tuple_type;

    typedef boost::zip_iterator<tuple_type> it_type;

    container l{1, 2, 3, 4};

    it_type begin(tuple_type(l.begin(), 0));
    it_type const end(tuple_type(l.end(), l.size()));

    // sample use with for loop
    for (it_type it = begin; it != end ; ++it)
    {
        int value = it->get<0>();
        int index = it->get<1>();
        // do whatever you want with value and index
    }

    // sample use with standard algorithm
    auto res = std::find_if(begin, end,
        [](boost::tuple<int, int> const & t)
        { return t.get<0>() > 2; }); // find first element greater than 2

    std::cout << "Value: " << res->get<0>() << '\n' <<
                 "Index: " << res->get<1>() << '\n';
}
于 2012-09-19T13:35:48.453 に答える
2

c ++ 11:

for (auto i=aVector.begin(); i!=aVector.end(); ++i) {
    cout << "I am at position: " << i-aVector.begin() << endl;
    cout << "contents here is: " << *i << endl;
}

c ++オールドスクール:

for (vector<int>::const_iterator i=aVector.begin(); i!=aVector.end(); ++i) {
    cout << "I am at position: " << i-aVector.begin() << endl;
    cout << "contents here is: " << *i << endl;
}
于 2012-09-19T13:17:30.183 に答える
0
for (iterator it = aVector.begin(), int index= 0; it!= aVector.end(); ++it, ++index)

これはコンパイルされません。しかし、それは実際には重要ではありません。なぜなら、私たちが話している限り、std::vectorインデックスによるアクセスは単純なポインター演算と逆参照であるため、実際にはイテレーターと同じくらい高速です。したがって、バージョン2は問題ありません。

ただし、さらに最適化します(速度が本当に心配な場合)。

for (int index = 0, size = aVector.size(); index < size; ++index)
{
    // access using []
}
于 2012-09-19T13:13:35.693 に答える
0

少し思い切って言うと、OPの最初のステートメントは、コンマ演算子の動作方法が原因でコンパイルされません。OPはiterator完全なタイプ名の代わりに省略形を使用していたと確信していますが、それは問題ではありません。

for (iterator it= aVector.begin(), int index= 0; it!= aVector.end(); ++it, ++index)

コンマ演算子は、2つの式を区切る(そして2番目の式の結果を返す)か、宣言内の変数を区切るために使用されます。for引数の最初の引数はどちらの形式でもかまいません。したがって、これらが異なる構文であるという事実がわかりにくくなります。

#include <vector>
#include <iostream>

int main()
{
    std::vector<int> aVector = {1,1,2,3,5,8,13};

    // option 1. Both loop variables declared outside the for statement, initialized inside the for statement
    int index1 = 0;
    decltype(aVector.begin()) it1;
    for (it1 = aVector.begin(), index1=0; it1!= aVector.end(); ++it1, ++index1)
    {
        std::cout << "[" << index1 << "]=" << *it1 << std::endl;
    }

    // option 2. The index variable declared and initialized outside, the iterator declared and initialized inside
    int index2=0;
    for (auto it2 = aVector.begin(); it2!= aVector.end(); ++it2, ++index2)
    {
        std::cout << "[" << index2 << "]=" << *it2 << std::endl;
    }

#if 0
    // option3 (the OP's version) won't compile. The comma operator doesn't allow two declarations.
    for (auto it3 = aVector.begin(), int index3=0 ; it3!= aVector.end(); ++it3, ++index3)
    {
        std::cout << "[" << index3 << "]=" << *it3 << std::endl;
    }
#endif
}
于 2021-05-17T22:36:39.490 に答える