にほたもるのブログ

にほたもるがゲームなどについて気ままに書くブログです。

arrayの参照渡し

どうも。にほです。

今日は、ゲームプログラミングの中で出てきた疑問点を解消したので、そのことに関して備忘録を残そうと思います。

※この記事は自分で調査した内容を記していますが、間違いがある可能性があることをご了承ください※

 

まず、arrayについてです。arrayとは、c++における標準のライブラリで、配列のような挙動を可能にしてくれるものです。また、配列とは違って、サイズを取得するなど、便利な機能がそろっています。なので、c++でプログラミングをしているなら、よほどの理由がない限り配列よりarrayを使った方がいいのかな?

 

ところで、配列では、関数に値を渡すとき、先頭のアドレスを渡しますよね。そこで以下のコードを見てみましょう。

#include <iostream>

using namespace std;

 

int rewrite(int arr[5])

{

    arr[0] = 10;

    arr[1] = 1652;

    arr[2] = 2768;

    arr[3] = -126;

    arr[4] = 0;

}

 

int main()

{

    int arr[5];

    for(int i = 0; i < 5; i++)

    {

        cout << arr[i] << endl;

    }

    for(int i = 0; i < 5; i++)

    {

        arr[i] = i * 3;

        cout << arr[i] << endl;

    }

   rewrite(arr);

   for(int i = 0; i < 5; i++)

   {

        cout << arr[i] << endl;

    }

}

f:id:nihotamor:20180209004023p:plain

このように、配列をそのまま関数で受け取っても値を自由に書き換えられてしまいます。これを防ぐには受け取り側でconstな変数を受け取るなどの手法があります。

では、このコードをarrayを使って書き換えてみましょう。

#include <array>

#include <iostream>
using namespace std;


void rewrite(array<int, 5> arr)

{

    arr[0] = 10;

    arr[1] = 1652;

    arr[2] = 2768;

    arr[3] = -126;

    arr[4] = 0;

}


int main()

{

    array<int, 5> arr;
    for (int i = 0; i < 5; i++)

    {

        cout << arr[i] << endl;

    }
    for (int i = 0; i < 5; i++)

    {

        arr[i] = i * 3;

        cout << arr[i] << endl;

    }

    rewrite(arr);
    for (int i = 0; i < 5; i++)

    {

        cout << arr[i] << endl;

    }
    return 0;

}

 それでは実行結果を見てみましょう。

f:id:nihotamor:20180209004946p:plain

このように、値は変わっていません。これは、arrayが値渡しされていて、要はarrayのコピーが関数に渡されているわけです。これを渡して関数の送り先で値を変更するにはどうしたらいいでしょうか。答えは参照渡しです。c++では、参照渡しをすることで、関数を渡した時に元の変数と同じアドレスの同じ値を扱うことになります。

#include <array>

#include <iostream>
using namespace std;


void rewrite(array<int, 5>& arr)

{

    arr[0] = 10;

    arr[1] = 1652;

    arr[2] = 2768;

    arr[3] = -126;

    arr[4] = 0;

}


int main()

{

    array<int, 5> arr;
    for (int i = 0; i < 5; i++)

    {

        cout << arr[i] << endl;

    }
    for (int i = 0; i < 5; i++)

    {

        arr[i] = i * 3;

        cout << arr[i] << endl;

    }

    rewrite(arr);
    for (int i = 0; i < 5; i++)

    {

        cout << arr[i] << endl;

    }
    return 0;

}

f:id:nihotamor:20180209005906p:plain

同じ値を扱っているので、この方法では書き換えることができました。このように、参照渡しを使うことで呼び出し元の変数を直接呼出し先で変更することができます。どこでも変数をいじれるのは危険なことではありますが、覚えておいて損はないでしょう。