PHP 傳值與傳址
物件傳值與傳址 by Value & by Reference
本章節將會學習傳值與傳址的概念(Call by value & Call by reference),以及透過實地演練來觀察兩者之間的差異。
當我們在建立原始變數時(數字、字串、布林),如果建立一個 a 變數,記憶體會提供一個位址存放 a 變數的資訊,假設這個記憶體位址是 0x100。如果這時候建立一個變數 b 並且讓變數 b = a 時,記憶體會另外建立一個獨立的位址(假設是 0x200)存放變數 b 的資訊。也就是說,雖然 a 和 b 的值相同,但其實是存在於兩個不同的記憶體。
如果是使用 Call by value 的方法去操作變數,因為 a 與 b 的記憶體位址是分開的,所以不會互相干擾,這種情況,我們就稱為 By Value。
記下來:
- 在 PHP 中,變數的操作預設是傳値(Call by value)
- 在 PHP 中,傳遞變數至方法時(Function),預設也是傳值(Call by value)
$a = 'hello';
$b = '';
function testCallByValue($a)
{
$a = 'world'; // 嘗試替換 $a 的值
}
testCallByValue($a);
echo $a
輸出結果:
hello
傳址 Call by reference
接下來看一下傳址的部分:
假設我們建立一個變數 a 為一個物件 Object 或 Function 時,記憶體會分配一個位址給變數 a(假設記憶體位址為 0x101)。這時候如果建立一個變數 b ,並且把變數 b = a 時,這時候記憶體不會再給變數 b 一個新的位址,而是將變數 b 指向變數 a 的記憶體位址 0x101。由於 a 和 b 實際上是指著相同的記憶體位址,因此 a 的值改變時, b 的值也會改變,這種情況我們就稱為 By Reference。
記下來:
在 PHP 中,Object 和 Function 變數的操作都是使用傳址 call by reference。
class Car
{
public $name = "";
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
}
$a = new Car ();
$a->setName("toyota");
$b = $a; // 將變數 b 指向變數 a 的記憶體位址
$b->setName('honda'); // 由於 a 和 b 都在操作相同的記憶體位置,因此變數 b 的更動會影響到變數 a。
echo $a->getName(); // 輸出結果: honda
強制傳址
由上面傳值與傳址的範例中,可以得知
PHP 預設:
變數的操作預設為傳值 Call by value
物件與方法的操作預設為傳址 Call by reference
但是你也可以使用 & 符號來強制讓變數傳址:
範例1: 宣告變數與賦值時使用 & 符號,強制讓變數傳址:
$A = "test";
$BB = $A;
$BB = "new test";
$CCC = &$BB; // 將變數 CCC 指向變數 BB 的記憶體位置
$CCC = "final test";
echo "變數A: $A, 變數BB: $BB, 變數CCC: $CCC";
輸出結果為:
變數A: test, 變數BB: final test, 變數CCC: final test=
範例2: 傳遞變數時使用 & 符號,強制讓變數傳址:
$var1 = "foo";
$var2 = "bar";
function changeThem($pama1, &$pama2){ // 將 var2 的記憶體位置傳入方法內
$pama1 = "FOO";
$pama2 = "BAR";
}
changeThem($var1, $var2);
print "var1: $var1, var2: $var2";
輸出結果為:
var1: foo, var2: BAR
範例3:傳遞物件至方法(function)
class Foo{
public $var1;
function __construct(){
$this->var1 = "foo";
}
public function printFoo(){
print $this->var1;
}
}
$foo = new Foo();
changeFoo($foo);
$foo->printFoo();
function changeFoo($foo){
$foo->var1 = "FOO";
}
輸出結果:
FOO
結論:
在PHP中:
變數預設為傳值 (Call by value)。
物件變數,為傳址 (Call by Reference)。
變數可以使用 & 符號強制傳址。
Variables containing primitive types are passed by value in PHP5.Variables containing objects are passed by reference.
參考資料:
請問,第一個範例:
回覆刪除callByValue();
echo $b;
是否應為空字串而非hello?
你說得對!
刪除當年留下不好的範例真慚愧..
謝謝你的留言,現在已經換上更容易懂的範例了