なぜ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
できました。確かに、そのパラメーターを値またはによって受け取ることができますが、それを保証する方法はありません。次のようなばかげたことをしないわけではありません。SomeFunctor
const&
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_iterator
sを取得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