はじめに
Effective C++ 第3版の3項9ページから勉強していきます。
今回は、「STLの反復子iteratorにおけるconst修飾子」についです。
Effective C++ 第3版 - 3項 可能ならいつでもconstを使おう -
STLの反復子iteratorにおけるconst修飾子
STLとは?
STL (Standard Template Library) とは、C++ の標準ライブラリの1つです。
iteratorとは?
iterator(イテレータ)は日本語では「反復子」と訳される。
配列やarrayクラス、vectorクラスの要素にアクセスする場合などに使われる。
iteratorは、ポインタをモデルにしています。
そのため、iteratorは、 T * 型ポインタのように振る舞います。
下のコードは、int * 型ポインタのように振る舞います。
std::vector<int> vec;
std::vector<int>::iterator niter = vec.begin(); // T * 型 ( int * 型)のようなもの
std::cout << "値 : " << *niter << std::endl;
std::cout << "アドレス : " << &(*niter) << std::endl;
const付きiterator
前回の投稿で、
const修飾子がアスタリスク(*)の左にあるときには、「ポインタが指し示すデータ」が不変、
const修飾子がアスタリスク(*)の右にあるときには、「ポインタそのもの」が不変となると書きました。
int x = 5;
int x2 = 3;
// const修飾子がアスタリスク(*)の左
const int *p2_x = &x; // ポインタは非const
// データはconst
*p2_x = x2; // コンパイルエラー
p2_x = &x2;
// const修飾子がアスタリスク(*)の右
int *const p3_x = &x; // ポインタはconst
// データは非const
*p3_x = x2;
p3_x = &x2; // コンパイルエラー
では、iteratorの場合はどうなるのでしょうか?
「iteratorが指し示すデータ」が不変の場合
std::vector<int>::const_iterator citer = vec.begin(); // ポインタでいう、const T * 型 (const int * 型)
*citer = 10; // コンパイルエラー // iterator(citer)が指すものの内容は変更不可
++citer; // iterator(citer)が別のものを指し示すことは可能
「iteratorそのもの」が不変の場合
const std::vector<int>::iterator iter = vec.begin(); // ポインタでいう、T * const 型 ( int * const 型)
*iter = 10; // iterator(iter)が指すものの内容を変更可能
++iter; // コンパイルエラー // iterator(iter)が別のものを指し示すことは不可
「iteratorが指し示すデータ」と「iteratorそのもの」が不変の場合
const std::vector<int>::const_iterator cciter = vec.begin(); // ポインタでいう、const T * const型( const int * const型)
*cciter = 10; // コンパイルエラー // iterator(cciter)が指すものの内容は変更不可
++cciter; // コンパイルエラー // iterator(cciter)が別のものを指し示すことは不可
以下に、勉強で使用したコードを示します。
サンプルコード
# include <iostream>
# include <vector>
int main(int argc, char* argv[]) {
std::cout << "3_const_itr.cpp" << std::endl;
std::vector<int> vec;
for (int i = 0; i < 5; i++) {
vec.push_back(i);
}
std::vector<int>::iterator niter = vec.begin(); // T * 型
const std::vector<int>::iterator iter = vec.begin(); // T * const 型
*iter = 10; // iterが指すものの内容を変更可能
// ++iter; // コンパイルエラー // iterが別のものを指し示すことは不可
std::vector<int>::const_iterator citer = vec.begin(); // const T * 型
// *citer = 10; // citerが指すものの内容は変更不可
++citer; // citerが別のものを指し示すことは可能
const std::vector<int>::const_iterator cciter = vec.begin();
// *cciter = 10; // コンパイルエラー
// ++cciter; // コンパイルエラー
}
実行結果
参考文献
・https://www.amazon.co.jp/gp/product/4621066099/ref=dbs_a_def_rwt_hsch_vapi_taft_p1_i0
・https://programming.pc-note.net/cpp/iterator.html