PHP7.0中的写时复制机制

LZ:PHP版本7.0

一、变量类型(数据类型)

  1. 标量类型:字符串,整形,浮点型,布尔型
  2. 复合类型:数组,对象
  3. 特殊类型:资源,空

二、所需概念

  1. 引用:某一变量的别名,指向同一空间,类似给某人取外号
  2. 浅拷贝:除了第一层是另辟空间值拷贝之外,其余层次都是引用
  3. 深拷贝:都是另辟空间进行值拷贝,都不是引用
  4. 写时复制:发生写的时候才会进行深拷贝

三、研究写时复制机制

/**
 * 知识点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

猜你喜欢

转载自blog.csdn.net/xwx_100/article/details/83783784