なぜcbeginとcendが C++11 で導入されたのだろうか?
beginこれらのメソッドを呼び出すと、およびの const オーバーロードと違いが生じるのはどのような場合endですか?
なぜcbeginとcendが C++11 で導入されたのだろうか?
beginこれらのメソッドを呼び出すと、およびの const オーバーロードと違いが生じるのはどのような場合endですか?
とても簡単です。ベクトルがあるとします:
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 を返します。
ニコル・ボーラスが彼の答えで言ったことを超えて、新しいautoキーワードを考えてみましょう:
auto iterator = container.begin();
では、 が定数でないコンテナ参照に対して定数演算子を返すautoことを確認する方法がありません。begin()したがって、次のようにします。
auto const_iterator = container.cbegin();
これを実際のユースケースとして考えてください
void SomeClass::f(const vector<int>& a) {
auto it = someNonConstMemberVector.begin();
...
it = a.begin();
...
}
itは非定数反復子であるため、代入は失敗します。最初に cbegin を使用した場合、反復子は正しい型を持っていたでしょう。
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()は現時点では不思議なことに欠落していますが、追加される可能性もあります。
この質問に出くわしました...すでに答えがあり、単なるサイドノードであることは知っています...
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