47865


c++のVectorなのですがこの`vector<int> x(a, a + sizeof(a) / sizeof(a[0]));`  
の a + sizeof(a) / sizeof(a[0])の a + とはどのような意味なのでしょうか？  
sizeof()によって配列aの要素数が求められるのはわかるのですがそれがなぜa +
されるのでしょうか？初歩的質問で申し訳ないのですが教えていただけますでしょうか？

[code]

            #include <vector>
            #include <iostream>
    
            using namespace std;
    
            int main()
            {
                int a[] = {1, 2, 3, 4, 5};
                              //ここです。
                vector<int> x(a, a + sizeof(a) / sizeof(a[0])); // 配列からベクトルを生成
    
                try {
                    for (vector<int>::size_type i = 0; i <= 10; i++) {
                        cout << "x[" << i << "] = " << x.at(i) << '\n';
                    }
                }
                catch (const out_of_range&) {
                    cout << "不正な添字です。\n";
                    return 1;                           // 強制終了
                }
            }
    
[/code]


CC BY-SA 4.0
2018-08-27T13:15:35.903
47855
2018-08-28T01:47:10.797
2018-08-28T01:47:10.797
4236
question
c++
配列のsizeof()

[code]

    #define elementsof(x) (sizeof(x)/sizeof((x)[0]))
    
[/code]

は（提示コードの `sizeof` の除算式部分をマクロ化したものですけど） [c](/questions/tagged/c "'c'
のタグが付いた質問を表示") 互換の単純配列の要素数を `size_t` 型で返すイディオムです。これが要素数 (提示例では `5` )
を返す理由は今回説明略（必要なら別途質問を挙げてくれると幸いです）。

一方で、ここで `x` を構築している `std::vector` のコンストラクタは  
<https://cpprefjp.github.io/reference/vector/op_constructor.html>  
の (5) で、単純配列の開始位置 `first` と終了位置 `last` を指定するものです。

`last` が開区間つまり `last` 自体は初期値に含まれないことは厳に理解が必要です。

さてコメント上での質疑応答 `int a[5];` があるとき `a+1` あるいは `a+5` の意味は？ ですが・・・ここんところは
[c](/questions/tagged/c "'c' のタグが付いた質問を表示") の配列取り扱い上の基礎中の基礎で、

  * 配列名は、特定文脈を除き [配列の最初の要素へのポインタ右辺値] に読み替えられる
  * 配列要素を指すポインタに加減算を行うと、要素１つ分の移動である

前者により `a` は `&a[0]` に半自動で変換されます。後者によりこれに `+1` すれば `(&a[0])+1` つまり `&a[1]`
であることを（この質疑応答で納得できなければいろいろ検索してみて）理解してください。そして更に

  * `a[5]` は存在しない要素なので、これをアクセスすることは違反だが `&a[5]` を演算することは認められている

のも知ってください (JIS X 3014:2003 5.7 加減演算子) これにより

[code]

    std::vector<int> x(a, a+5); // 提示例の sizeof 除算式は要素数でしたよね
    
[/code]

は `a` という配列の `a[0]` から `a[4]` の５つの値を初期値とする `std::vector` の構築ということになります。この書き方で

  * `&a[5]` と書くことができるが
  * `a[5]` にアクセスすることはないので未定義動作にならない
  * 値 `5` は `sizeof` 式で求めるようにすると、要素数の変更に自動的に追従できる

そもそも論として

[code]

    for (i=0; i<5; ++i) {
        printf("%d\n", a[i]);
    }
    
[/code]

を `for (i=0; i<=4; ++i)` と書かないのと同じで [c](/questions/tagged/c "'c'
のタグが付いた質問を表示") で配列を扱う際には半開区間を使うのが自然であるため `vector` のコンストラクタも半開区間を採用しています。

`&a[5]` を演算すること自体を違反にすると

[code]

    for (p=&a[0]; p<&a[5]; ++p) printf("%d\n", *p);
    
[/code]

と書けなくなっちゃいますよね。


CC BY-SA 4.0
2018-08-27T23:38:33.427
47865
2018-08-28T00:31:57.637
2018-08-28T00:31:57.637
8589
8589
47855
answer