210

なぜcbegincendが C++11 で導入されたのだろうか?

beginこれらのメソッドを呼び出すと、およびの const オーバーロードと違いが生じるのはどのような場合endですか?

4

7 に答える 7

244

とても簡単です。ベクトルがあるとします:

std::vector<int> vec;

いくつかのデータを入力します。次に、いくつかのイテレータを取得したいと思います。たぶんそれらを回してください。多分にstd::for_each

std::for_each(vec.begin(), vec.end(), SomeFunctor());

C++03 では、取得したパラメーターを自由に変更SomeFunctorできました。確かに、そのパラメーターを値またはによって受け取ることができますが、それを保証する方法はありません。次のようなばかげたことをしないわけではありません。SomeFunctorconst&

const std::vector<int> &vec_ref = vec;
std::for_each(vec_ref.begin(), vec_ref.end(), SomeFunctor());

さて、紹介しcbegin/cendます:

std::for_each(vec.cbegin(), vec.cend(), SomeFunctor());

SomeFunctorこれで、ベクトルの要素を変更できない構文上の保証が得られました (もちろん、const キャストなしでは)。明示的にconst_iteratorsを取得SomeFunctor::operator()するため、 で呼び出されconst int &ます。パラメータを としてint &受け取ると、C++ はコンパイラ エラーを発行します。


C++17 には、この問題に対するより洗練された解決策がありますstd::as_const。まあ、少なくとも range-based を使うとエレガントですfor:

for(auto &item : std::as_const(vec))

これは単に、const&提供されたオブジェクトに a を返します。

于 2012-08-17T07:24:36.390 に答える
69

ニコル・ボーラスが彼の答えで言ったことを超えて、新しいautoキーワードを考えてみましょう:

auto iterator = container.begin();

では、 が定数でないコンテナ参照に対して定数演算子を返すautoことを確認する方法がありません。begin()したがって、次のようにします。

auto const_iterator = container.cbegin();
于 2012-08-17T07:27:09.240 に答える
15

これを実際のユースケースとして考えてください

void SomeClass::f(const vector<int>& a) {
  auto it = someNonConstMemberVector.begin();
  ...
  it = a.begin();
  ...
}

itは非定数反復子であるため、代入は失敗します。最初に cbegin を使用した場合、反復子は正しい型を持っていたでしょう。

于 2012-08-17T07:34:35.130 に答える
8

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1674.pdfから:

プログラマーが非 const コンテナーからでも const_iterator を直接取得できるようにする

彼らはこの例を挙げました

vector<MyType> v;

// fill v ...
typedef vector<MyType>::iterator iter;
for( iter it = v.begin(); it != v.end(); ++it ) {
    // use *it ...
}

ただし、コンテナーのトラバーサルが検査のみを目的としている場合、コンパイラーが const-correctness 違反を診断できるようにするために、const_iterator を使用することが一般的に推奨される方法です。

ワーキング ペーパーでは、アダプタ テンプレートについても言及されていることに注意してください。これらのテンプレートは現在、 および として最終化されておりstd::begin()std::end()ネイティブ アレイでも動作します。対応するstd::cbegin()std::cend()は現時点では不思議なことに欠落していますが、追加される可能性もあります。

于 2012-08-17T07:24:47.457 に答える
6

この質問に出くわしました...すでに答えがあり、単なるサイドノードであることは知っています...

auto const it = container.begin()それならタイプが違うauto it = container.cbegin()

の違いint[5](ポインターを使用します。これには begin メソッドがありませんが、違いをうまく示しています...しかし、 c++14 for std::cbegin()andstd::cend()で機能します。これは、本質的にここにあるときに使用する必要があるものです)...

int numbers = array[7];
const auto it = begin(numbers); // type is int* const -> pointer is const
auto it = cbegin(numbers);      // type is int const* -> value is const
于 2014-06-05T20:34:34.160 に答える