PHP7.0中的寫時複製機制
阿新 • • 發佈:2018-11-19
LZ:PHP版本7.0
一、變數型別(資料型別)
- 標量型別:字串,整形,浮點型,布林型
- 複合型別:陣列,物件
- 特殊型別:資源,空
二、所需概念
- 引用:某一變數的別名,指向同一空間,類似給某人取外號
- 淺拷貝:除了第一層是另闢空間值拷貝之外,其餘層次都是引用
- 深拷貝:都是另闢空間進行值拷貝,都不是引用
- 寫時複製:發生寫的時候才會進行深拷貝
三、研究寫時複製機制
/** * 知識點1:寫時複製 <==> 在必要的時候才會進行深拷貝(即發生寫的時候才會進行深拷貝) * 知識點2:在PHP中並不是所有的資料型別都可通過value賦值就可以進行深拷貝,比如物件、資源就無法 * 知識點3:好處:因為只讀共享,寫時分離(即只讀類似使用引用,寫時取消引用,並建立新的指向),所以可提升效率 */ /** * @return int 1 測試字串賦值是否是寫時複製 * */ function test_string(): int { $s_origin = 'origin'; $s_deep_copy = $s_origin; $s_origin .= 'copy'; if ($s_origin !== $s_deep_copy){ var_dump($s_origin, $s_deep_copy); return 1; } return 0; } /** * @return int 1 測試整型、浮點型、布林賦值是否是寫時複製 */ function test_int_float_bool($origin, $chg_origin): int { $deep_copy = $origin; $origin = $chg_origin; if ($origin !== $deep_copy){ var_dump($origin, $deep_copy); return 1; } return 0; } /** * @return int 1 測試陣列賦值是否是寫時複製 */ function test_array(): int { $arr_origin = array(); $arr_deep_copy = $arr_origin; array_push($arr_origin, 1); if ($arr_origin !== $arr_deep_copy){ var_dump($arr_origin, $arr_deep_copy); return 1; } return 0; } /** * Class A 測試物件賦值是否是寫時複製 */ class A { public $b; public function test_object(): int { $object_origin = new self(); $object_deep_copy_1 = $object_origin; //嘗試賦值 進行深拷貝 $object_deep_copy_2 = clone $object_deep_copy_1; //嘗試語言結構clone 進行深拷貝 $object_origin->b = 2; var_dump($object_origin->b, $object_deep_copy_1->b, $object_deep_copy_2->b); //只有clone 才進行深拷貝 if (($object_origin !== $object_deep_copy_1) && $object_origin !== $object_deep_copy_2){ return 1; } return 0; } } function test_resource(){ $tmp_file_name = './test.txt'; $file_handler = fopen($tmp_file_name, 'w'); $file_handler_deep_copy = $file_handler; fwrite($file_handler, '哈哈'); var_dump($file_handler, $file_handler_deep_copy); if ($file_handler !== $file_handler_deep_copy){ return 1; } fclose($file_handler); if (file_exists($tmp_file_name)){ unlink($tmp_file_name); } return 0; } /** * 美化程式碼 * @param $callback array 測試陣列 * @param $type array 測試型別陣列 */ function beatiful_code($callback, $type){ if (is_array($callback) && is_array($type) && count($callback) == count($type)){ array_map(function ($cb_index, $tp_index){ echo '===========' . $tp_index . '============'.PHP_EOL; $cb_index(); echo '===========' . $tp_index . '============'.PHP_EOL.PHP_EOL; }, $callback, $type); } else{ print_r('測試引數錯誤'); return; } } $callback = [ function (){ // 字串支援寫時複製 var_dump('返回值:'.test_string()); },function (){ // 整型支援寫時複製 var_dump('返回值:'.test_int_float_bool(1, 2)); },function (){ // 浮點型支援寫時複製 var_dump('返回值:'.test_int_float_bool(1.1, 2.1)); },function (){ // 浮點型支援寫時複製 var_dump('返回值:'.test_int_float_bool(true, false)); },function (){ // 陣列支援寫時複製 var_dump('返回值:'.test_array()); },function (){ // 物件不支援寫時複製 var_dump('返回值:'.(new A())->test_object()); },function (){ // 資源型別不支援寫時複製 var_dump('返回值:'.test_resource()); } ]; $type = [ 'string', 'int', 'float', 'bool', 'array', 'object', 'resource' ]; beatiful_code($callback, $type); /* result: ===========string============ string(10) "origincopy" string(6) "origin" string(13) "返回值:1" ===========string============ ===========int============ int(2) int(1) string(13) "返回值:1" ===========int============ ===========float============ float(2.1) float(1.1) string(13) "返回值:1" ===========float============ ===========bool============ bool(false) bool(true) string(13) "返回值:1" ===========bool============ ===========array============ array(1) { [0]=> int(1) } array(0) { } string(13) "返回值:1" ===========array============ ===========object============ int(2) int(2) NULL string(13) "返回值:0" ===========object============ ===========resource============ resource(5) of type (stream) resource(5) of type (stream) string(13) "返回值:0" ===========resource============ */ // 由此可以看出,PHP7.0版本除了物件、資源之外,其餘資料型別均已實現寫時複製
四、結論
PHP7.0版本除了物件,資源之外,其餘資料型別均已實現寫時複製
五、型別轉換
1、自動型別轉換
$a = '100' + 200; //字串自動轉化成整型
print_r($a);
2、強制型別轉換
(string):轉化為字串
(int)(integer):轉化為整型
(float)(double)(real):轉化為浮點型float
(bool)(boolean):轉化為布林型
(array):轉化為陣列
(object):轉化為物件
(unset):轉化為null