質問: " << x.at(i) << '\n'; } } catch (const out_of_range&) { cout << "不正な添字です。\n"; return 1; // 強制終了 } } ```
回答: ``` #define elementsof(x) (sizeof(x)/sizeof((x)[0])) ``` は(提示コードの `sizeof` の除算式部分をマクロ化したものですけど) [c](/questions/tagged/c "'c' のタグが付いた質問を表示") 互換の単純配列の要素数を `size_t` 型で返すイディオムです。これが要素数 (提示例では `5` ) を返す理由は今回説明略(必要なら別途質問を挙げてくれると幸いです)。 一方で、ここで `x` を構築している `std::vector` のコンストラクタは の (5) で、単純配列の開始位置 `first` と終了位置 `last` を指定するものです。 `last` が開区間つまり `last` 自体は初期値に含まれないことは厳に理解が必要です。 さてコメント上での質疑応答 `int a[5];` があるとき `a+1` あるいは `a+5` の意味は? ですが・・・ここんところは [c](/questions/tagged/c "'c' のタグが付いた質問を表示") の配列取り扱い上の基礎中の基礎で、 * 配列名は、特定文脈を除き [配列の最初の要素へのポインタ右辺値] に読み替えられる * 配列要素を指すポインタに加減算を行うと、要素1つ分の移動である 前者により `a` は `&a[0]` に半自動で変換されます。後者によりこれに `+1` すれば `(&a[0])+1` つまり `&a[1]` であることを(この質疑応答で納得できなければいろいろ検索してみて)理解してください。そして更に * `a[5]` は存在しない要素なので、これをアクセスすることは違反だが `&a[5]` を演算することは認められている のも知ってください (JIS X 3014:2003 5.7 加減演算子) これにより ``` std::vector x(a, a+5); // 提示例の sizeof 除算式は要素数でしたよね ``` は `a` という配列の `a[0]` から `a[4]` の5つの値を初期値とする `std::vector` の構築ということになります。この書き方で * `&a[5]` と書くことができるが * `a[5]` にアクセスすることはないので未定義動作にならない * 値 `5` は `sizeof` 式で求めるようにすると、要素数の変更に自動的に追従できる そもそも論として ``` for (i=0; i<5; ++i) { printf("%d\n", a[i]); } ``` を `for (i=0; i<=4; ++i)` と書かないのと同じで [c](/questions/tagged/c "'c' のタグが付いた質問を表示") で配列を扱う際には半開区間を使うのが自然であるため `vector` のコンストラクタも半開区間を採用しています。 `&a[5]` を演算すること自体を違反にすると ``` for (p=&a[0]; p<&a[5]; ++p) printf("%d\n", *p); ``` と書けなくなっちゃいますよね。