萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 網路程式設計 >> PHP 程式設計

PHP 賦值運算子完整指南:基本賦值、複合賦值、傳值與引用賦值深度解析

前言

賦值運算子(=)是 PHP 程式中最頻繁使用的運算子,但其行為細節(運算式值、複合賦值、傳值 vs 引用、物件賦值語意)常被忽略。本文系統整理賦值運算子完整語法、記憶體模型與實務陷阱。

一、基本賦值:不只是「等於」

1.1 語意與運算式值

<?php
$a = 3;        // 將 3 賦予 $a,整個運算式值為 3
echo $a = 5;   // 輸出 5,且 $a 變為 5

// 串聯賦值:從右向左結合
$a = $b = $c = 10; // $c=10, $b=10, $a=10
?>

1.2 巧用運算式值

<?php
$a = ($b = 4) + 5; // $b=4,運算式值 4,+5 = 9 賦予 $a
// $a=9, $b=4
?>

二、複合賦值運算子:算術、字串、位元、位移

2.1 完整列表與等價展開

運算子名稱等價展開範例
+=加法賦值$a = $a + $b$a=10; $a+=5; // 15
-=減法賦值$a = $a - $b$a=10; $a-=3; // 7
*=乘法賦值$a = $a * $b$a=10; $a*=2; // 20
/=除法賦值$a = $a / $b$a=10; $a/=2; // 5.0
%=取模賦值$a = $a % $b$a=10; $a%=3; // 1
.=字串串接賦值$a = $a . $b$a='Hi'; $a.='!'; // 'Hi!'
&=位元 AND 賦值$a = $a & $b$a=6; $a&=3; // 2
|=位元 OR 賦值$a = $a | $b$a=4; $a|=3; // 7
^=位元 XOR 賦值$a = $a ^ $b$a=5; $a^=3; // 6
<<=左移賦值$a = $a << $b$a=1; $a<<=2; // 4
>>=右移賦值$a = $a >> $b$a=8; $a>>=1; // 4

2.2 實戰:字串累積與位元旗標管理

<?php
// 字串累積(效能優於反覆串接新字串)
$sql = 'SELECT * FROM users';
$sql .= ' WHERE active = 1';
$sql .= ' ORDER BY created_at DESC';

// 位元旗標:權限管理
class Permission {
    const READ   = 1; // 0b001
    const WRITE  = 2; // 0b010
    const EXEC   = 4; // 0b100
}
$userPerm = Permission::READ;
$userPerm |= Permission::WRITE; // 加入寫入權限 0b011 = 3
if ($userPerm & Permission::READ) { /* 可讀 */ }
$userPerm ^= Permission::WRITE;   // 移除寫入(切換)
?>

三、傳值賦值 vs 引用賦值:記憶體模型核心差異

3.1 傳值賦值(預設行為)

<?php
$a = 10;
$b = $a;      // 複製值
$b = 20;
echo $a; // 10(互不影響)

// 陣列亦為傳值複製(Copy-on-Write 優化)
$arr1 = [1,2,3];
$arr2 = $arr1;
$arr2[0] = 99;
var_dump($arr1); // [1,2,3] 未變
var_dump($arr2); // [99,2,3]
?>

3.2 引用賦值 &

<?php
$a = 10;
$b = &$a;     // $b 參考 $a 同一記憶體位址
$b = 20;
echo $a; // 20(同步變化)

// 陣列引用
$arr1 = [1,2,3];
$arr2 = &$arr1;
$arr2[0] = 99;
var_dump($arr1); // [99,2,3] 同步變化
?>

3.3 物件賦值:特殊的「引用語意」

PHP 5 起,物件變數儲存的是「物件識別碼」(handle),而非物件本體。

<?php
class Foo { public $val = 1; }

$obj1 = new Foo();
$obj2 = $obj1;        // 複製 handle,指向同一物件
$obj2->val = 2;
echo $obj1->val; // 2(影響同一物件)

$obj3 = new Foo();
$obj1 = $obj3;        // $obj1 指向新物件,$obj2 仍指向舊物件
echo $obj2->val; // 2

// 真正複製物件:使用 clone
$obj4 = clone $obj1;
$obj4->val = 99;
echo $obj1->val; // 2(互不影響)
?>

四、foreach 中的賦值陷阱

4.1 值傳遞(預設)

<?php
$arr = [1,2,3];
foreach ($arr as $v) { $v *= 2; }
var_dump($arr); // [1,2,3] 原陣列未變
?>

4.2 參考傳遞 &$v(可修改原陣列)

<?php
$arr = [1,2,3];
foreach ($arr as &$v) { $v *= 2; }
unset($v); // 重要:解除參考,避免後續誤用
var_dump($arr); // [2,4,6]
?>

4.3 陣列鍵值參考 $k => &$v

<?php
$arr = ['a'=>1, 'b'=>2];
foreach ($arr as $k => &$v) {
    $v = strtoupper($k) . $v;
}
unset($v);
var_dump($arr); // ['a'=>'A1', 'b'=>'B2']
?>

五、常見錯誤與最佳實踐

錯誤模式問題修正
if ($a = 5)賦值而非比較,永遠為 trueif ($a == 5) 或 if (5 === $a)(Yoda 條件)
foreach 後未 unset($v)$v 保留最後元素參考,後續操作污染陣列習慣加上 unset($v)
函式參數預期引用未加 &函式內修改不影響外部函式簽名 function(&$var),呼叫端 func($var)
大量陣列複製導致記憶體飆升Copy-on-Write 機制下寫入才複製,但大陣列仍需謹慎傳遞引用、使用產生器、或資料庫分頁

結語

賦值運算子是 PHP 程式的基石,深入理解「運算式有值」、「複合賦值語法糖」、「傳值/引用/物件 handle 三種記憶體語意」與「foreach 參考陷阱」,能寫出記憶體效率高、行為可預測、無副作用驚喜的程式碼。

copyright © 萬盛學電腦網 all rights reserved