fei*_*iny 9 php reference null-coalescing-operator
Q1:我认为??在以下情况下将不会执行任何操作:
$a = [1, 2];
foreach ($a ?? [] as &$v) {
$v++;
}
var_dump($a);
Run Code Online (Sandbox Code Playgroud)
但为什么?
array(2) {
[0]=>
int(1)
[1]=>
int(2)
}
Run Code Online (Sandbox Code Playgroud)
Q2:这更奇怪:
foreach ($a = [1, 2] as &$v) {
$v++;
}
var_dump($a);
// output
array(2) {
[0]=>
int(1)
[1]=>
int(2)
}
Run Code Online (Sandbox Code Playgroud)
我的想法:我认为表达式不可引用,但foreach捕获错误或以某种方式然后复制。有效的参考资料:
$a = 1;
$c = &$a;
Run Code Online (Sandbox Code Playgroud)
不工作:
$a = 1;
$c = &($a);
$c = &($a ?? []);
$c = &($a + 1);
Run Code Online (Sandbox Code Playgroud)
??复印吗?我只是不想用 if 为 null 来包装foreach,if (isset($a))并且$a会foreach失败。
TL;DR对于您的情况,您可以考虑以这种方式使用空合并运算符:
$a = $a ?? [];
foreach ($a as &$v) { ... }
Run Code Online (Sandbox Code Playgroud)
或者,根本不使用引用,通过使用array_map()或 使用键在底层数组中进行修改。
$a = [1, 2];
foreach ($a ?? [] as &$v) {
$v++;
}
var_dump($a);
Run Code Online (Sandbox Code Playgroud)
合并运算符使用原始数组的副本,然后应用右侧操作数 if null。因此,迭代发生在原始数组的副本上。
您可以将其与以下内容进行比较:
$a = [1, 2];
$x = $a ?? [];
$x[1] = 4;
var_dump($a); // [1, 2]
Run Code Online (Sandbox Code Playgroud)
compiled vars: !0 = $a, !1 = $v
line #* E I O op fetch ext return operands
-------------------------------------------------------------------------------------
8 0 E > ASSIGN !0, <array>
9 1 COALESCE ~3 !0
2 QM_ASSIGN ~3 <array>
3 > FE_RESET_RW $4 ~3, ->8
... rest of looping code
Run Code Online (Sandbox Code Playgroud)
的第一个操作数FE_RESET_RW是将要迭代的哈希变量,您可以看到它~3而不是!0($a在您的代码中),这正是您期望发生的情况。
foreach ($a = [1, 2] as &$v) {
$v++;
}
Run Code Online (Sandbox Code Playgroud)
这里发生的情况是,赋值的返回值$a = [1, 2]被用作要迭代的数组。
您可以将此行为与类似的行为进行比较:
$x = $a = [1, 2];
$x[0] = 4; // modify in-place
var_dump($a); // [1, 2]
Run Code Online (Sandbox Code Playgroud)
$x = $a = [1, 2];
$x[0] = 4; // modify in-place
var_dump($a); // [1, 2]
Run Code Online (Sandbox Code Playgroud)
同样,$2是 的第一个操作数FE_RESET_RW,它是赋值结果,因此迭代不会针对!0($a在您的代码中) 发生。