2011-01-19 9 views
1

は、PHPで私たちはこのような何か書くことができます。「参照」の使用方法にはあいまいさがありますか?例えば

class C { 
    var $x; 

    function __construct($x) { 
     $this->x = $x; 
    } 

    function __toString() { 
     return (string)$this->x; 
    } 
} 

function f1($obj) { 
    $obj->x = 2; 
} 

$a = new C(1); 
f1($a); 
echo $a; // 2 

を、いくつかは、これはあなたがそれらのプロパティを変更することができるので、オブジェクトは、参照によって渡され、それらの変更は、クラスの外に反映されていることを示していることだと思います。すなわち、オブジェクトはプリミティブがコピーされていない。

しかし、我々はこれを書くことができます。

function f2($obj) { 
    $obj = new C(2); 
} 


$b = new C(1); 
f2($b); 
echo $b; // 1 

今オブジェクトはすべての参照渡しされていません示唆しています。実際には、オブジェクトはコピーされる(値渡される)が、は深くはないコピーされる。 $objがコピーされますが、$xはまだ同じものを参照しています。

「参照」という言葉は両方の意味を持つと聞いていますが、一部の人は、PHPが参照渡しであると言い、他のものは渡し渡しと言うでしょう。

function f3(&$obj) 

のような関数を定義すると言うとき

我々はPHPが参照渡しであると言うなら、私たちは何を意味するのですか? その関数はオブジェクトへの参照を取ります。これは、最初の意味が間違っていることを示しています。

しかし、C++のような言語やC#の構造体はどうですか?私のC++は少し錆びていますが、クラスを渡すときにクラス全体が実際にディープコピーされると思います。そのため、できる限り関数が参照を参照するようにしたり、ポインタを使用することをおすすめします。 C#では、構造体とクラスがどのように渡されるかに違いがあります。

値渡しではない場合、このディープコピー動作とは何ですか?

私たちは3つの行動とそれらを記述するための2つのフレーズしか持たないと思われ、これはコミュニティに多くの混乱を招いています。

ヘック、私はちょうどあなたの誰かが私がここに何か間違って書いたと言ってくるのを待っています。要約する


、3つの動作は次のとおり

  1. オブジェクトのみオブジェクトがコピーされ
  2. (オブジェクトとそのプロパティがクローン化された)ディープコピーである(その特性はまだを参照私たちは、tのそれぞれを呼び出す必要がありますどのようなオブジェクトはすべて

技術的にコピーされません

  • メモリの同じチャンク)、ヘイスの行動?パス - バイ - ???

  • +0

    いつか(またはおそらくない)、... PHPは、引数に 'const'キーワードを実装しますが、これはいかなるあいまいさを削除します: ) – netcoder

    答えて

    0

    変数とオブジェクトへの参照を区別する2つのことがあります。パラメータ$ objに他の値を代入しない限り、関数外とまったく同じオブジェクトを扱います。他のオブジェクトを代入した後、変数は変更されましたが、オブジェクトへの参照だけを変数に渡したため、外部の変数は元のオブジェクトを指していません...

    1

    私がドリュータを持っていた場合、.netの "オブジェクト参照"という用語は、オブジェクトがルーチンに渡されるほとんどの場合、 idは値によって渡されます(Dictionary.TryGetValueのように、オブジェクトIDが参照渡しされるような場合もあります)。同じ用語を使用してオブジェクトIDとパラメータ渡しのタイプを記述すると、混乱が生じます。

    1

    C++では、最初の2つは両方とも値渡しと呼ばれます。ディープコピーの深さは、問題のクラスのコピーセマンティクスに依存します。プログラマが指定する必要があります(クラスによっては、リソースへのハンドルであり、浅くコピーする必要があります。 - コピー)。 Pythonには深く浅いコピーのためのライブラリ関数があります。ディープコピーは、クローニングとも呼ばれます。 C++とJavaで。

    第3は、参照渡しと呼ばれます。これは、呼び出し先がインプレースで変更できるものを渡す一般的な用語です。

    (Cは、それが参照の概念を持っていないので、この規則の例外ですが、渡しのポインタはほとんど参照渡しと同じです。)最初

    +0

    @downvoter:説明してください。 –

    2

    まず物事:あなたが欲しいかもしれませんReferences Explainedを読む。


    通常、変数は常に値によって渡されます。重要なのは、実際に価値があることです。

    変数が「オブジェクトを保持している」場合は、オブジェクトへの参照がです。

    したがって、あなたがオブジェクトから参照が渡され

    function foo($bar) {} 
    

    のような関数定義を持っている場合。そのため、オブジェクトを変更することができます。

    しかし、関数内の変数に新しい値を割り当てると、参照を別のもので上書きするだけで、そのオブジェクトへの参照が失われます。

    したがって、関数に渡す変数$someVarがあると仮定すると、$bar$someVarは同じ値(つまり参照)を持ちますが、メモリ内に独自の場所があります。

    前:

    $someVar -> object_reference ┐ 
    
               ├ -> object 
    
    $bar  -> object_reference ┘ 
    

    後:

    $someVar -> object_reference -> object 
    
    
    
    $bar  -> other_value 
    

    今すぐ関数定義は、その後

    function foo(&$bar) {} 
    

    のようなものであるならば、あなたは実際に参照が渡されます場所は他の変数のメモリ。

    foo($someVar)で関数を呼び出すと、$bar$someVarと同じ場所を指します。つまり、新しい値を割り当てると、その特定の場所がメモリに上書きされます。前

    $someVar ┐ 
    
          ├ -> object_reference -> object 
    
    $bar  ┘ 
    

    後:

    $someVar ┐ 
    
          ├ -> other_value   object 
    
    $bar  ┘ 
    
    +0

    それで...質問に答えてください。あなたは何を言っているのですか?オブジェクトはオブジェクト*への参照によって渡され、それ以外の場合はメモリ*の場所への参照を渡していますか?プリミティブはどうですか?または深くコピーされたオブジェクト?どちらのシナリオでも「参照」という言葉を使用していますので、完全修飾されていなければあいまいさがありますか? – mpen

    +0

    @マーク:この用語はあいまいではありません。両方の状況で同じ概念を記述しているため、この用語を使用するのは正しいです。パラメータが '&'記号で定義されていなければ、関数が参照を受け付けるとは決して言いません。また、オブジェクトを渡すとプロパティを変更できます。 2番目の例では、渡されたオブジェクトのプロパティでは操作していませんが、変数に新しい値を代入していることに注意してください。参考文献は、他に何かを独自に定義するものです。他のオブジェクト指向言語でも同じ動作が見られます。 –

    +0

    @マーク:申し訳ありませんが、わかりやすく説明できない場合は、 –

    関連する問題