Apr 2, 2008

参照呼び出し・値呼び出しとは

参照呼び出しって何? - 檜山正幸のキマイラ飼育記

参照呼び出し・値呼び出しというのは、「参照(参照の値、ポインタなど)」が引数として渡されるか「値」が引数として渡されるかという違いを表しているのではありません。実引数がどのように仮引数に渡されるのかという違いを表しているのです。はっきり言ってしまえば、実引数が左辺値として評価可能な式のときに、仮引数にその左辺値が渡されるのが「参照呼び出し(渡し)」、右辺値が渡されるのが「値呼び出し(渡し)」です。

言うまでもなく、Javaなどで採用している(プリミティブ型以外の)オブジェクトの参照という「値」を渡す方式は、「値呼び出し」です。誤って「参照呼び出し」と説明している解説はものすごくたくさんありますが。Javaで参照を値渡ししたときにできるのはその参照先のオブジェクトに対する操作であって、その変数がどのオブジェクトへの参照を格納しているかを操作することはできません。なぜなら値渡しだからです。

C++での簡単な例を下に示しておきます。

#include <iostream>

int dup(int i);
void dup2(int *i);
void dup3(int& i);

int main() {
  int i = 123;

  // 値呼び出し (iという式の右辺値を渡す)
  i = dup(i);
  std::cout << i << std::endl;

  // 値呼び出し (&iという式の右辺値、すなわちアドレス値を渡す)
  dup2(&i);
  std::cout << i << std::endl;

  // 参照呼び出し
  dup3(i);
  std::cout << i << std::endl;
}

int dup(int i) {
  i *= 2;
  return i;
}

void dup2(int *i) {
  *i *= 2;
}

void dup3(int& i) {
  i *= 2;
}

実はdup2とdup3はコンパイル結果としてほぼ同等なものが得られます。dup3の呼び出しは、dup3のシグネチャを参照して変数iの参照の値(アドレス)を関数に渡すようにコンパイルされ、dup3は参照の値がスタックかレジスタに積まれているものとしてコンパイルされるからです。

しかし、重要なのはそういう実装がどうなっているかということではなく、dupやdup2では「字面上」右辺値しか渡せないのに、dup3では左辺値を渡せているということなのです。

About Me

My Photo

つくばで働く研究者

Total Pageviews

Amazon

Copyright 2012 Ogawa::Buzz | Powered by Blogger
Design by Web2feel | Blogger Template by NewBloggerThemes.com