foreachの中で参照渡しのunsetしたときの不思議

PHPで、配列の中の特定の要素を削除するときといえばだいたい、
↓な感じかと思います。

<?php

$a = ['a' => 1, 'b' => 2, 'c' => 3];

foreach($a as $key => $val){
    if($val === 2){
        unset($a[$key]);
    }
}
array(2) {
  ["a"]=>
  int(1)
  ["c"]=>
  int(3)
}


けど、foreachで参照渡しができると知ったので、こんな書き方を試してみた。

<?php

$a = ['a' => 1, 'b' => 2, 'c' => 3];

foreach($a as &$val){
    if($val === 2){
        unset($val);
    }
}

しかし!!!!!!

array(3) {
  ["a"]=>
  int(1)
  ["b"]=>
  int(2)
  ["c"]=>
  &int(3)
}

消えてない!!!!

<?php

$a = ['a' => 1, 'b' => 2, 'c' => 3];

foreach($a as &$val){
    if($val === 2){
        unset($val);
    }
    $val = '^o^';
}

ただ、unsetのifブロックの外で代入すると、

array(3) {
  ["a"]=>
  string(3) "^o^"
  ["b"]=>
  int(2)
  ["c"]=>
  &string(3) "^o^"
}

unsetした要素以外には代入がされた。


なんでこうなるのか、詳しい人に聞いてもわからなかった…。
ストレートに考えると『unsetで参照が解除されただけ』ということなのだろうか。
分かる人教えてください…。