例えば「じゃがいもと人参を受け取ってカレーを作って返す関数」というものを例にお話します。
その関数はコードで書くとこんな感じになりますよね。
typedef struct {
... // じゃがいも構造体の中身
} Potato;
typedef struct {
... // 人参構造体の中身
} Carrot;
Curry CookCurry(Potato p, Carrot c) {...}
Cではこの関数は実は問題がある可能性があります、なぜならCでの関数は「値渡し」しかできないからです。つまりこの関数を呼び出すときには、内部的にはこの関数のためだけにPotato構造体とCarrot構造体を複製して渡す事になります。複製にかかるコストは構造体の大きさに比例しますから潜在的にものすごい量のコピーが起きる可能性があります。
ところでJavaではオブジェクトは関数に対して参照渡しされるので、構造体のコピーが起きる事はありません。関数に対して「人参は冷蔵庫の野菜室にあるもの、じゃがいもは足元の箱に入ってるものを使ってね」のように材料の実体ではなく、材料の場所の情報そのものを渡すので材料の複製を行う必要がなくなります。ただしこれは良い事ばかりではなく「シチューに使うつもりで冷蔵庫に入れておいた人参なのに無くなってる!」みたいな行き違いが起きる事もありえます。ですのでImmutableパターンという物で「見るだけにしか使わないなら参照経由、実際に書き換えを行うときには複製する」みたいに迂回することもあります。これが値渡しと参照渡しの違いです。
ところでCでは値渡ししかできないのですが「場所の情報」を表現する方法があって、それをポインタと言います。
Curry CookCurry(Potato* p, Carrot* c) {...}
こんな感じで「じゃがいもの在り処と人参の在り処」を渡す関数として定義すれば、その在り処が書かれたメモ自体は値として複製され渡されますが、実体としては参照渡しと同じことが行われます。参照で渡すのですからそこでの注意点はJavaと同様です。
3か月(3か月更新)