Skip to content

7. 関数

7.4 [発展] 参照渡し

INFO

ここではやや難しい内容を扱っているため、一度飛ばして、練習問題に進んでも構いません。

7.4.1 アドレス

一度関数から離れて「変数」について考えてみる。 以前触れた通り、変数は0と1の組み合わせによって表されているが、プログラムが変数の値を参照するときには、「変数の住所」の情報を持っていなければならない(でなければ、どの変数がどれか分からなくなってしまう)。 この変数の住所のことをアドレスと呼ぶ。変数には「値」と「アドレス」の二種類の情報が備わっている。具体的には、メモリの前から何バイト目に変数が格納されているかの情報が与えられる。

アドレスは変数の前に&をつけることで取得することができる。

cpp
#include <iostream>
using namespace std;

int main() {
    int x = 4;
    cout << x << endl;
    cout << &x << endl;
}
Output
4
0x7fffe13bd944

アドレスは人によって・実行するたびに変わることに注意。(変わらないこともある) 出力に0xがついているが、これは16進数であることを表している。 10~15に当たる1桁の値として、abcdefが用いられる(探してみると0-9とa~fしかない文字列を時々見つけられる。これらは16進数である事が多い)。

  • int型のアドレス」の型はint *である。
  • アドレスから元の変数に戻すには、アドレスの前に*をつける。
cpp
#include <iostream>
using namespace std;

int main() {
    int x = 4;
    int *p = &x;
    cout << p << endl;
    *p += 1;
    cout << x << endl;
}
Output
0x7ffc62a31e34
5

ここで*p += 1と書いているが、pxのアドレスが入っているので、x += 1と書くのと同じことが起きる。

7.4.2 値渡しと参照渡し

cpp
#include <iostream>
using namespace std;

int triple(int x) {
    x = x*3;
    return 0;
}

int main() {
    int x = 4;
    triple(x);

    cout << x << endl;
}

「引数」の節で、関数を呼び出した側の変数は、関数内で操作しても変わらないという事を説明した。

これについてもう少し詳しく触れると、関数を呼び出すとき、与えられた引数は複製され(= 新しい変数が作られて)、関数内で使用される。

つまり変数の値のみを渡している。この事を値渡しと呼ぶ。

main関数で作ったxtripleの中で変更できるようにするには、xのアドレスを関数に渡せば良い。

cpp
#include <iostream>
using namespace std;

int triple(int *x) {
    *x = (*x)*3;
    return 0;
}

int main() {
    int x = 4;
    triple(&x);

    cout << x << endl;
}
Output
12

これをアドレス渡しと呼ぶ。関数にわたすのは変数の値ではなく「変数のアドレス」なので、呼び出し側はtriple(&x)と記述する。

しかし、&x*xをいちいち書くのは面倒なので、これを簡略化した記法が存在する。下のコードを書けば、上のコードと書いたのと同じことになる。

cpp
#include <iostream>
using namespace std;

int triple(int &x) {
    x = x*3;
    return 0;
}

int main() {
    int x = 4;
    triple(x);

    cout << x << endl;
}
Output
12

型の部分をintからint &に変えるだけで、変数のポインタを渡したことになり、main関数のxtriple関数から変更できるようになるのである。

この機能を参照と言い、この書き方を参照渡しと呼ぶ。