我似乎無法得到任何一致的信息。不同的消息來源似乎說不同的事情和老的php.net本身(似乎)不明確說明這一點 - 雖然,我必須承認,我只是看了一眼。PHP5對象是否通過引用傳遞?
在我身邊掠過「重」的對象的情況下,我需要通過引用傳遞,但我不想讓打字:
function foo(TypeName& $obj)
,如果我能逃脫簡直
function foo(TypeName $obj)
那麼標準說什麼呢?
我似乎無法得到任何一致的信息。不同的消息來源似乎說不同的事情和老的php.net本身(似乎)不明確說明這一點 - 雖然,我必須承認,我只是看了一眼。PHP5對象是否通過引用傳遞?
在我身邊掠過「重」的對象的情況下,我需要通過引用傳遞,但我不想讓打字:
function foo(TypeName& $obj)
,如果我能逃脫簡直
function foo(TypeName $obj)
那麼標準說什麼呢?
通過引用傳遞(並分配)對象。不需要使用操作員的地址。
授予我鍵入的內容過於簡單但適合您的目的。該documentation狀態:
一個PHP5 OOP的關鍵點的那 經常提到的是「物 被引用在默認情況下通過」。 這並非完全正確。這 部分使用一些例子糾正了一般思想 。
一個PHP引用是一個別名,它允許兩個不同的變量 寫入相同的值。從PHP5, 開始,一個對象變量不再包含對象本身作爲值的 。它只有 包含一個對象標識符 它允許對象訪問器找到 實際的對象。當一個對象是由參數發送的 ,返回或將 分配給另一個變量時,不同的 變量不是別名:它們包含標識符的 副本,它將 指向同一對象。
有關更詳細的解釋(解釋過簡化以及標識符)檢查出this answer。
從PHP 5開始,所有對象都被傳遞並通過引用來分配。
在PHP 4中,您仍然需要通過明確使用&
運算符來指定希望引用傳遞對象的位置。
可以通過參考 一個變量傳遞到功能所以該函數可以 修改變量。語法是 如下:
<?php function foo(&$var) { $var++; } $a=5; foo($a); // $a is 6 here ?>
注:有一個 函數調用無符號 - 只有函數定義 。單獨的函數定義 足以正確傳遞參考的參數 。截至PHP 5.3。0,當您在 foo(& $ a);中使用&時,您將收到一條警告,指出「通話時間通過引用」爲 。
在PHP 5中, 對象模型的基礎設施被改寫對象句柄運行 。除非你通過使用 明確克隆一個對象,否則你將永遠不會使用 創建你的對象的場景重複對象 。在PHP 5中,有 既不需要通過 參考由 參考
因此,因此,你需要使用function foo(&$var)
語法的唯一一次傳遞對象,也沒有給他們分配的,如果是$ var可能不是的一個實例一類。
我對你的陳述採取了迂腐的例外「因此,只有當你需要使用<< pass by reference >>語法時,如果$ var可能不是一個類的實例」。 還有另外一個重要的情況,你確實希望使用一個類的實例的引用... 如果 - 作爲調用函數的結果,你希望你傳遞的參數指向(指向)一個*不同的實例,那麼你將需要函數來接受通過引用傳遞的參數,並且在函數中你可以將該參數分配給不同的實例。 – 2013-05-15 13:50:40
是從PHP5開始,對象通過引用傳遞。沒有必要明確地做到這一點。
http://www.php.net/manual/en/migration5.oop.php
在PHP 5中有個新對象模型。 PHP的對象處理已經完全重寫,可以獲得更好的性能和更多的功能。在以前的PHP版本中,對象被處理爲基本類型(例如整數和字符串)。這種方法的缺點是,在分配變量或作爲參數傳遞給方法時,會在語義上覆制整個對象。在新方法中,對象由句柄引用,而不是由值引用(可以將句柄看作對象的標識符)。
簡短回答是是。從Objects and references:
一個PHP5 OOP的關鍵點的那 經常提到的是「物 被引用在默認情況下通過」。 這並非完全正確。這 部分使用一些例子糾正了一般思想 。
一個PHP引用是一個別名,它允許兩個不同的變量 寫入相同的值。從PHP5, 開始,一個對象變量不再包含對象本身作爲值的 。它只有 包含一個對象標識符 它允許對象訪問器找到 實際的對象。當一個對象是由參數發送的 ,返回或將 分配給另一個變量時,不同的 變量不是別名:它們包含標識符的 副本,它將 指向同一對象。
要緊的是,在讓你擔心的話,你永遠都不會是一個對象的副本,除非你明確地使用克隆關鍵字在函數調用。無論是別名還是標識符都不會改變這一事實。
爲了進一步說明,我有一個作爲'functionName(\ Response $ response)'傳遞的PSR-7響應對象的例子,就像我在PHP 5+中編寫這個'functionName(\ Response&$ response)'一樣?當這是真的,那麼我必須重新思考我的小項目中的一切。 – 2017-01-28 09:46:01
@ZsoltOroszlány在[PSR-7](http://www.php-fig.org/psr/psr-7/)中,根據定義,響應必須是不可變的。這意味着實現必須明確地調用'clone',如在例如[Slim框架](https://github.com/slimphp/Slim/blob/3.7.0/Slim/Http/Response.php#L182)。 – 2017-01-28 14:41:00
它似乎更精確一點,對象的值是通過值傳遞的,但對象本身的值是一個指針。這不同於傳遞參考。
在http://www.php.net/manual/en/language.oop5.references.php列出的例子很好。在第一組中,$ a = NULL;不會影響$ b,因爲$ a只是一個指針。在第二組中,$ c = NULL;導致$ d也爲NULL,因爲$ d是對$ c的引用。
<?php
class A {
public $foo = 1;
}
$a = new A;
$b = $a;
$a->foo = 2;
$a = NULL;
echo $b->foo."\n"; // 2
$c = new A;
$d = &$c;
$c->foo = 2;
$c = NULL;
echo $d->foo."\n"; // Notice: Trying to get property of non-object...
?>
只是一個例子,其中通過「對象」,由參考是有用的:
class RefTest1
{
public $foo;
public function __construct(RefTest2 &$ref = null)
{
$this->foo =& $ref;
}
}
class RefTest2
{
public $foo;
public function __construct(RefTest1 &$ref = null)
{
$this->foo =& $ref;
}
}
class RefTest3
{
public $foo;
public function __construct(RefTest2 &$ref = null)
{
$this->foo =& $ref;
}
}
class DoCrossRef
{
public $refTest1;
public $refTest2;
public function __construct()
{
$this->refTest1 = new RefTest1($this->refTest2);
$this->refTest2 = new RefTest2($this->refTest1);
}
public function changeReference()
{
$this->refTest1 = new RefTest3($this->refTest2);
}
}
在結束RefTest1
保持到RefTest2
基準和周圍的其他方法,也如果RefTest2
對象不存在當時RefTest1
已創建。
在致電DoCrossRef->changeReference()
之後,RefTest2
對象也持有對新的RefTest3
對象的引用。
下面是確認對象按引用傳遞的另一個示例。
<?php
// discussion: https://stackoverflow.com/questions/2715026/are-php5-objects-passed-by-reference#_=_
class A {
public $foo = 1;
}
class B {
function inc($obj) {
$obj->foo++;
}
}
$objA = new A();
$objB = new B();
$objB->inc($objA);
echo "[" . $objA->foo . "]"; // Outputs [2]
因此,您可以傳遞一個對象標識符的引用? – 2013-10-24 10:21:05
當你傳遞一個對象時,你仍然「通過價值」傳遞。但是,「價值」不是對象本身。值是對象標識符,哪些訪問器( - >)用於查找對象。所以無論何時你傳遞一個對象或者將一個對象分配給別的東西,它都「感覺」像傳遞引用。當使用 - >時,它「感覺」像一個別名。但從技術上講,它不是別名,而是價值是對象標識符的值的副本。如果它是一個別名,重新分配一個完全不同的值會將所有的別名改變爲新的值,但是你會看到它不會使它們成爲別名。 – OCDev 2015-01-08 13:41:33
@OCDev所以每次該對象被克隆?有點資源浪費。 – 2017-06-17 15:38:23