Javaで参照渡しすることとCでポインタを渡すことの違いは何ですか?

StackOverflow https://stackoverflow.com/questions/600651

質問

Javaを数か月間勉強していたが、今ではCを学び始めています。

少し混乱していますが、オブジェクトを参照渡しすることと、そのオブジェクトにポインターを渡すことは同じことであるという印象を受けました。 Cのように、実際にはあちこちに小さなアスタリスクとアンパサンドを振りかけなければなりません。最近、会話の中で、違いがあると確信しました!

参照渡しとポインター渡しの違いは何ですか?

役に立ちましたか?

解決

Java Cも参照渡しはありません。両方とも厳密に値渡しです。

Pass-by-Referenceセマンティクスとは、メソッドのパラメーターの値を変更すると、呼び出し側が引数の変更を確認することを意味します。

今、あなたは考えているかもしれません:"しかしそれはJavaの場合です!メソッドの実行中にオブジェクトを変更すると、呼び出し元はその変更を認識します。" オブジェクトはパラメータではありません。パラメータは変数ですちょうど-そして、その変数の値を変更しても、呼び出し側には表示されません。例:

public void foo(Object x)
{
    x = null;
}

public void caller()
{
    Object y = new Object();
    foo(y);
    // y is still not null!
}

パラメータが参照により本当に渡された場合、 y はその後nullになります。代わりに、 y の値は単なる参照であり、その参照は値で渡されます。 「参照」という言葉が両方の用語ですが、それらは異なるものです。

C#パラメータの受け渡しに関する私の記事を参照してください。 Java did が参照渡しのセマンティクスを持っている場合、C#が ref キーワードを使用する場合(のみ)にできるようになります。

myへのコメントもご覧ください。トピックに関連するスタックオーバーフローの回答

他のヒント

  

違いは、Javaではすべてのオブジェクトの受け渡しが自動的にポインターで行われることだと思いました。Cのように、実際にはあちこちに小さなアスタリスクとアンパサンドを振りかける必要があります。

概念的、それはまったく正しい。私たちが物足りな人であれば(それは良いことです)、オブジェクトがJavaでまったく渡されないと言うことさえできます。渡されるのは「ポインタ」だけであり、Javaではこれを参照と呼びます。すべての間接化は自動的に行われます。したがって、" objref-> foo"を実行すると、 " objref.foo"の代わりにCではポインターを使用するためドットを使用できませんが、Javaでは、とにかくメンバーにアクセスするために他に何も知らないため、ドットを使用できます。 Cでは、ポインターを渡すことができます(そして、ここでは実際にポインターと呼ばれます) オブジェクト自体を渡すことができます。その場合、コピーが渡されます。 Cでは、ポインターが参照するオブジェクトに、スターまたは「-」を使用して間接的にアクセスします。 Javaでは、オブジェクトにアクセスする唯一の方法は、ドット(objref.member)を使用することです。

私たちが再び教訓的である場合(今、より重要になっています)、JavaとCのどちらにも「参照渡し」はありません。 Javaで渡すのは、オブジェクトへの参照/ポインターであり、Cでは、オブジェクトのコピー(明らかな場合)を渡すか、オブジェクトへのポインターのコピーだけを再度渡します。したがって、JavaとCの両方の場合に渡されるのは、オブジェクトのアドレスです。 JavaとCの両方でコピーされるプリミティブなJava型については話さないCのそれに関して。

違いはわずかです。アセンブリレベルでは、どちらの場合もオブジェクトのアドレスが関数に渡されます。ただし、ポインターの場合、パラメーターは、ターゲットオブジェクトの変更に使用できる独立したポインター(* pch = 'x')または別のオブジェクトへのアクセスに使用できます(pch =" newstr")。参照ケースでは、パラメーターはターゲットオブジェクトに自動的に間接化されます。

ポインターは参照を含む変数であると考えています。 で&メモリー方向(reference)を取得できます。*を使用すると、メモリー方向のコンテンツにアクセスできます。 私は本 Cプログラミング言語を提案します。

よろしく

True 参照渡しは、割り当てることができることを意味します参照への新しい値。この新しい値は、呼び出されたメソッド内のように、呼び出しコンテキストで表示されます。

Javaでは、これは不可能です。オブジェクト参照は値で渡されます

いくつかのこと

  • Cには参照がありません(C ++にもかかわらず)
  • Javaにはポインターがありません
  • ポインタと参照の違いは、ポインタは実際に計算できるメモリアドレスであるということです。参照を計算することはできません
  • JavaおよびCは値渡し(オブジェクトをJavaで渡す場合、参照は関数にコピーされます)

(C ++ではなく)Cを学習している場合、参照はありません。

用語「参照渡し」 Cの場合、単に値が格納されるアドレスとしてポインタを渡すことを意味し、関数がその値を変更できるようにします。 それ以外の場合は、値で渡します。つまり、変数のコピーがスタック上に生成され、変更は影響しません。

これは多くの点でJavaで見られるものと似ていますが、Javaで明示的にポインターに変換したり、逆参照したりする必要がない点が異なります。つまり、ポインターを渡すと、アドレスがスタックにコピーされるので、関数がポインターが変更する場合(ポインターが指すデータではなく)、関数を完了すると変更が消えます。同様に、Javaでオブジェクト参照を渡す場合、オブジェクトの内容を変更できます(たとえば、関数を呼び出すことにより)が、変数を変更してanothrオブジェクトを指すようにすると、一度離れても効果はありません。

C ++(Cのように見える)を使用していた場合は、参照渡しできます。この場合、ポインターを処理する必要はなく、関数の変数を変更すると実際に外部値が直接変更されます(何か他のものを指すようにできないことを除いて)。

Eric Lippertによるこれに関する最近の記事があります。彼はC#コンパイラのプログラマですが、彼が言うことはすべて、Javaなどの他のGC言語に拡張するのに十分な一般性を持っています。

http:// blogs .msdn.com / ericlippert / archive / 2009/02/17 / references-are-not-addresses.aspx

記事からの引用:

  

ポインタは厳密に「より強力」です。参照より;ポインタを使用して実行できる参照を使用して実行できること。 [...]

     

ポインターは通常、アドレスとして実装されます。アドレスは、「バイトの配列」へのオフセットである数字です。つまり、プロセスの仮想アドレス空間全体です。 [...]

     

これらのすべての理由から、参照を仕様のアドレスとして説明しません。仕様では、参照型の変数が「参照を格納する」とだけ述べています。オブジェクトに追加し、それをどのように実装するかについては完全に曖昧にします。同様に、ポインター変数には「アドレス」が格納されます。オブジェクトの、これもかなり曖昧なままです。参照がアドレスと同じであるとは言いません。

     

したがって、C#では、参照はオブジェクトを参照できる漠然としたものです。参照を逆参照する以外に参照を使用して何かを実行したり、他の参照と同等かどうかを比較することはできません。 C#では、ポインターはアドレスとして識別されます。

     

参照とは対照的に、アドレスを含むポインターを使用すると、さらに多くのことができます。アドレスは数学的に操作できます。互いに減算したり、整数を追加したりできます。彼らの法的運営は、それらが「ファンシーナンバー」であることを示しています。 " array"へのインデックスそれはプロセスの仮想アドレス空間です。

C / C ++に精通している読者は、おそらくオブジェクト参照が表示されることに気付いています。 ポインタに似ている。この疑いは、本質的に正しいです。オブジェクト参照は メモリポインタに似ています。主な違いとJavaの安全性への鍵は、 実際のポインターと同じように参照を操作することはできません。したがって、 任意のメモリ位置を指す、または整数のように操作するオブジェクト参照。

  • javaはサポートされていません&演算子を使用すると、javaでオブジェクトアドレスを取得できます。
  • Javaの参照は、たとえばオブジェクトによって行われます

MyClass object1 = new MyClass();

MyClass object2 = object1;

i.e。 object1とobject2は別々の異なるオブジェクトを参照していると考えるかもしれません。 ただし、これは間違っています。代わりに、このフラグメントの実行後、object1とobject2は両方とも同じオブジェクトを参照します。他のいずれかの効果を変更した場合。

*初期化後にオブジェクトのアドレスを変更することはできません すなわちMyClass obj = new MyClass(); c ++の参照として、オブジェクトを使用すると、オブジェクトインスタンス値のみを変更できます

注:javaは特別な機能を提供します         object1はnullに設定されていますが、object2はまだ元のオブジェクトを指します。

javaについてはわかりませんが、C#またはVB.netでは、値または参照で渡すことができます

refrenceで渡す例

    static void Main(string[] args)
    {
        int x = 1;
        Foo(ref x);
        Console.WriteLine(x.ToString());//this will print 2
    }

    private static void Foo(ref int x)
    {
        x++;
    }

xが1に等しいことに注意してください。ただし、メソッドFooを呼び出し、Fooでxが1増加したときに参照によってxを渡すと、元の値も増加します

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top