参照渡し | Programming Place Plus 用語集

トップページ用語集

名称 🔗

解説 🔗

プログラミングにおいて、関数呼び出し先でも同じ実体が参照されるように引数を渡す方法のことです。

参照渡しでは、呼び出し元で実引数として指定した変数が、呼び出し先の関数の仮引数でまったく同じ実体を参照するように渡されます。そのため、関数内で仮引数のを変更すると、呼び出し元の変数の値も変更されます。

対応する用語に値渡し(あたいわたし)があります。値渡しの場合、実引数と仮引数は異なる実体として扱われ、呼び出し先の関数内で仮引数の値を変更しても、呼び出し元の変数の値は変更されません。これは値だけを渡していると考えることができます。

また、プログラミング言語によっては、参照を値で渡すという考え方をして、すべてが値渡しであると説明されるものもあります(参照の値渡し)。Java や Python などがこの考え方を採用しています。

C言語の場合 🔗

C言語C++ において、ポインタ型の引数で渡すことを参照渡しと表現することがありますが、これは正確ではありません。

ポインタで渡すことが参照渡しであるのなら、以下のサンプルプログラムのように、仮引数の値を変更したときに、呼び出し側の変数の値も変更されていなければなりません。

#include <stdio.h>

int a = 10;
int b = 20;

void f(int* p)
{
    p = &b;  // 仮引数の値を変更する
}

int main(void)
{
    int* p = &a;
    printf("%d (%p)\n", *p, p);

    f(p);
    printf("%d (%p)\n", *p, p);
}

実行結果:

10 (00007FF790DAC000)
10 (00007FF790DAC000)

実行結果のとおり、関数 f の中で仮引数 p の値を変更しても、呼び出し元の変数 p の値は変更されません。

ポインタ型の引数で渡すことは、メモリアドレスのような参照先を表現する値を、値渡しで渡しているのだといえます。標準規格の用語ではありませんが、ポインタ渡しと呼ぶことがあります。

C++ の場合 🔗

C++ でもC言語の場合と同様に、ポインタ型の引数を渡すことは参照渡しではありませんが、C++ には参照型があるため、参照型の引数で渡すことで参照渡しが可能です。ただし、C++ の参照型の値の変更(参照先の変更)はできず、r = 0; のような代入は参照先の値の変更になるため、参照型の仮引数自体の値を変更することはできません。

#include <iostream>

int a {10};

void f(int& r)
{
    std::cout << "in function: " << r << " (" << &r << ")\n";
    r = 20;  // これは参照先の値の書き換え
}

int main(void)
{
    int& r = a;

    std::cout << "before call: " << r << " (" << &r << ")\n";
    f(r);
    std::cout << "after call: " << r << " (" << &r << ")\n";
}

実行結果:

before call: 10 (00007FF78D42D000)
in function: 10 (00007FF78D42D000)
after call: 20 (00007FF78D42D000)

メモリアドレスによる確認により、関数 f に渡した実引数の r と、仮引数の r が同じ実体を参照していることが分かります。また、関数内で参照先の値を書き換えた影響が、呼び出し側でも確認できます。


参考リンク 🔗

更新履歴 🔗


用語集のトップページへ

Programming Place Plus のトップページへ



はてなブックマーク に保存 Facebook でシェア X で ポストフォロー
LINE で送る noteで書く rss1.0 取得ボタン RSS
管理者情報 プライバシーポリシー
先頭へ戻る