3

私は、C および C++ での参照渡しの概念全体と、Java での値渡しのみの同様の概念を知っています。しかし、ある観点から見ると、すべてが値渡しですよね。C では、変数のポインターを関数に渡します。したがって、参照の値を関数に渡しているだけです。これが、参照変数の値を関数に渡すだけなので、Java が参照渡しをサポートしていないと言う理由です。したがって、参照を値で渡します。C++ では、引数を渡すことができ、関数はこの形式を使用して同じメモリ位置で動作するため、参照渡しの方法があります。

void swap(int &x, int &y)

しかし、C でのポインターによる参照渡しは、ポインターを値渡しするだけです。

void swap(int* x, int* y)

質問が少しばかげているように思えるかもしれませんが、私が持っているコンセプト全体に大きな穴があると感じています. では、参照による呼び出しの実際の定義は何ですか?これは、別のコンテキストでの値による呼び出しの単なる疑似名ですか?

4

4 に答える 4

4

参照渡しとは、呼び出された関数のパラメーターが、呼び出し元の渡された引数と同じになることを意味します (値ではなく、ID - 変数自体)。値渡しとは、呼び出された関数のパラメーターが、呼び出し元に渡された引数のコピーになることを意味します。値は同じですが、ID (変数) は異なります。したがって、呼び出された関数によって行われたパラメーターへの変更は、ある場合には渡された引数を変更し、別の場合には、呼び出された関数のパラメーターの値を変更するだけです (これは単なるコピーです)。

C++ での簡単な例

#include <iostream>

void by_val(int arg) { arg += 2; }
void by_ref(int&arg) { arg += 2; }

int main()
{
    int x = 0;
    by_val(x); std::cout << x << std::endl;  // prints 0
    by_ref(x); std::cout << x << std::endl;  // prints 2

    int y = 0;
    by_ref(y); std::cout << y << std::endl;  // prints 2
    by_val(y); std::cout << y << std::endl;  // prints 2
}
于 2015-01-10T17:34:46.663 に答える
3

2 つの主なポイント:

  • C には参照による呼び出しはありません。
  • 値渡しと参照渡しは違います。それらは同じではありません。

値渡し:呼び出された関数は、スタックに新しい変数セットを作成し、引数の値をそれらにコピーします。

参照渡し:呼び出される関数に値を渡す代わりに、元の変数への参照/ポインターが渡されます。

なぜプログラマーは、「参照による受け渡し」が実際には「値による参照の受け渡し」であると言うのでしょうか?

元の変数への参照/ポインターを渡す際、実際にはオブジェクト/アドレスは値によって渡されます。したがって、参照渡しは値渡しであると言えますが、これは参照渡しが値渡しの疑似名であることを意味するものではありません。この2つの違いは、この回答でよく説明されています。抜粋をコピーしています:

URLをお伝えする場合は、参照渡しです。その URL を使用して、私が見ているのと同じ Web ページを表示できます。そのページが変更された場合、私たちは両方とも変更を確認します。URL を削除すると、そのページへの参照が破棄されるだけで、実際のページ自体は削除されません。

ページを印刷してあなたに渡す場合、で渡します。あなたのページはオリジナルの分離されたコピーです。その後の変更は表示されず、行った変更 (印刷物への落書きなど) は元のページには表示されません。印刷物を破棄すると、実際にはオブジェクトのコピーが破棄されますが、元の Web ページはそのまま残ります。

于 2015-01-10T17:33:38.890 に答える
1

「参照」の定義を与えずに、「参照渡し」が本当に「値渡し参照」であるとは言えません。

Javaでは、呼び出しで渡されたパラメーターの値を変更せずに、関数内で参照である仮パラメーターの値を変更できるため、ステートメントは true (最初はおおよそ) です。

void f(Object param) {
  param = null;
}

void g() {
  Object o = new Object();
  System.out.println(o);
  f(o);
  System.out.printn(o);
}

2 つの print ステートメントがまったく同じ結果になることは誰もが知っています。実際、Javaには参照渡しはなく、渡すことができるのは参照のみです。引数を渡す方法は 1 つしかありません: 値渡しです。

C++ では、これはまったく異なります。関数内の参照パラメーターの値を変更すると、呼び出しで渡されるパラメーターが変更されます。

void f(int &param) {
  param = 0;
}

void g() {
  int i=12;
  cout << i << endl;
  f(i);
  cout << i << endl;
}

すべての C++ プログラマーは、2 番目の出力が 0 を表示することを知っています (最初の出力は 12 です)。

したがって、C++ では、「参照渡し」が「参照を値渡し」であるとは言えません。C++ 参照には値がなく、メモリ チャンクに関連付けられた名前にすぎません (標準セクション 8.3.2 参照: [注: 参照はオブジェクトの名前と考えることができます。—終了注] )。内部f()には、2 つの名前を持つ変数が 1 つだけあります。もちろん、C++ 参照の実装のほとんどが隠しポインターであることに異議を唱えるかもしれません。ただし、非表示のポインターを使用して参照を実装することを回避できる場合が多いことに注意する必要があります (標準セクション 8.3.2/7 参照。参照にストレージが必要かどうかは指定されていません)...したがって、C++ ではステートメントは次のようになります。有効ではありません。C++ には、パラメータを渡す方法が 2 つあります。値による方法と参照による方法です。

于 2015-01-10T19:00:20.937 に答える