在记忆中 PHP 简单变量的拷贝是按值传递,数组和对象的拷贝是按引用传递,即通过引用来实现。

简单变量和对象好理解:

<?php

// 简单变量的拷贝
$a = 'human';
$b = $a;
$b = 'cat';
var_dump($a); // string 'human' (length=5) // 对象的拷贝
class A{}
$a = new A();
$b = $a;
$b->name = 'jack';
var_dump($a); // object(A)[1] public 'name' => string 'jack' (length=4)

对象 $a 和 对象 $b 的内存地址指向了同一个地方,即针对 $a 和 $b 所做的操作都针对同一个实例。

PHP 中可以通过 clone 关键字按值拷贝对象:

<?php

class A{
public $name = 'Vardy';
}
$a = new A();
$b = clone $a;
$b->name = 'dee';
var_dump($a); // object(A)[1] public 'name' => string 'Vardy' (length=5)
var_dump($b); // object(A)[2] public 'name' => string 'dee' (length=3)

  

数组:

<?php

// 数组的拷贝
$a = ['human', 'orc'];
$b = $a;
$b[0] = 'elve';
var_dump($a);
// array (size=2)
// 0 => string 'human' (length=5)
// 1 => string 'orc' (length=3)

这样看,数组的拷贝是按值传递的.

另一个例子 数组的迭代器:

<?php

$a = ['human', 'orc', 'elven', 'undead'];
next($a); $b = $a; // 此时指针位置也随着数组的复制而复制 var_dump(current($a)); // string 'orc' (length=3)
var_dump(current($b)); // string 'orc' (length=3)

当数组拷贝时,数组的指针位置也随着复制。

(next:http://php.net/manual/zh/function.next.php

current:http://php.net/manual/zh/function.current.php

<?php

$a = ['human', 'orc', 'elven', 'undead'];
end($a);
next($a); // 数组指针非法,返回 FALSE $b = $a; var_dump(current($a)); // string 'human' (length=5)
var_dump(current($b)); // boolean false

当数组在拷贝前,指针的位置是非法时,拷贝后分别打印两个数组指针所指向的当前单元时,出现了不一样的情况。

原因是数组变量发生拷贝后,两个变量中先发生写操作的,其指针被初始化,即指向第一个元素,而 current 方法也会产生写操作,因此 $a 的数组指针当前指向的是 'human',而 $b  current 方法则返回 FALSE。

以下代码同理, $b 首先发生了写操作:

<?php

$a = ['human', 'orc', 'elven', 'undead'];
end($a);
next($a); $b = $a; $b[] = 'dwarf'; var_dump(current($a)); // boolean false
var_dump(current($b)); // string 'human' (length=5)

  

解析:数组的拷贝是值传递。PHP 在管理内存方面有一个机制叫写时复制(COW,Copy On Write),保证了变量间复制值不浪费内存:当一个变量的值复制到另一个变量时,PHP 没有为复制值使用更多的内存,相反,它会更新符号表来说明两个变量拥有相同的内存块,所以当执行下面的代码时并没有创建一个新的数组:

<?php

$a = ['human', 'orc', 'elven', 'undead'];
$b = $a;

当修改了 $a 或 $b 任意一个副本时,PHP 将分配所需的内存来进行复制:

$b[] = 'dwarf';

  

 

参考:

php基础语法之数组和数组指针

php中引用&的真正理解-变量引用、函数引用、对象引用

Programming PHP 3rd Edition

PHP 数组的拷贝是按值传递 or 按引用传递的更多相关文章

  1. js按值传递和按引用传递

    摘要:js的数据类型有种划分方式为 原始数据类型和 引用数据类型. 原始数据类型 存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置.栈区包括了 变量的标识符和变量的值. ...

  2. PHP中对象是按值传递还是按引用传递?

    1.首先,什么是按值传递和按引用传递? 按值传递就是仅仅把值传递过去,相当于传递的是值的拷贝,而按引用传递传递的是内存的地址. 在 PHP5 中,如果按引用传递,就是将 zval 的地址赋给另一个变量 ...

  3. Java的按值传递和按引用传递解说

    在网上看到的一个帖子解释Java的按值传递和按引用传递,感觉挺全面,就转过来,以供以后学习参考: 1:按值传递是什么 指的是在方法调用时,传递的参数是按值的拷贝传递.示例如下: public clas ...

  4. 转------深入理解--Java按值传递和按引用传递

    引言 最近刷牛客网上的题目时碰到不少有关Java按值传递和按引用传递的问题,这种题目就是坑呀,在做错了n次之后,查找了多方资料进行总结既可以让自己在总结中得到提高,又可以让其他人少走弯路.何乐而不为? ...

  5. Java参数按值传递?按引用传递

    有时候在想,java在调用方法时候究竟是按值传递还是按引用传递,之前有人说是基本数据类型按值传递,引用类型按引用传递.一时间,似乎都有道理. 笔者在此不追究字眼上的辨别识字能力,把自己对这个问题的理解 ...

  6. JavaScript中函数参数的按值传递与按引用传递(即按地址传递)

    首先声明一句:JavaScript中所有函数的参数都是按值传递的!不存在按引用传递! 在讲传递参数之前我们先来讲一下指针. 学过C指针的应该都知道,指针变量中保存的是一个地址,程序可以根据所保存的地址 ...

  7. JS是按值传递还是按引用传递?【转载】

    最近遇到个有趣的问题:“JS中的值是按值传递,还是按引用传递呢?” 在分析这个问题之前,我们需了解什么是按值传递(call by value),什么是按引用传递(call by reference). ...

  8. java-IO流-字符流-FileReader、FileWriter、自定义小数组的拷贝、BufferedReader、BufferedWriter、readLine()和newLine()方法、LineNumberReader、使用指定的码表读写字符

    ###21.01_IO流(字符流FileReader) * 1.字符流是什么     * 字符流是可以直接读写字符的IO流     * 字符流读取字符, 就要先读取到字节数据, 然后转为字符. 如果要 ...

  9. javascript数组操作(创建、元素删除、数组的拷贝)

    这篇文章主要介绍了javascript数组操作,包括创建.元素的访问.元素删除.数组的拷贝等操作,还有其它示例,需要的朋友可以参考下 1.数组的创建 复制代码 代码如下: var arrayObj = ...

随机推荐

  1. javascript判断图片是否加载完成方法整理

    有时候我们在前端开发工作中为了获取图片的信息,需要在图片加载完成后才可以正确的获取到图片的大小尺寸,并且执行相应的回调函数使图片产生某种显示效果.本文主要整理了几种常见的javascipt判断图片加载 ...

  2. Python函数讲解

    Python函数

  3. time和datetime时间戳---python

    time模块 time模块提供各种操作时间的函数 说明:一般有两种表示时间的方式:        1.时间戳的方式(相对于1970.1.1 00:00:00以秒计算的偏移量),时间戳是惟一的 2.以数 ...

  4. linux安装wine

    1.添加PPA sudo add-apt-repository ppa:ubuntu-wine/ppa 2.更新列表 sudo apt-get update 3.安装Wine sudo apt-get ...

  5. Markdown入门

    http://www.jianshu.com/p/1e402922ee32/ 有道云笔记支持Markdown

  6. NameError: name 'sys_platform' is not defined

    pip install --upgrade distribute

  7. testng教程之testng.xml的配置和使用,以及参数传递

    昨天学习了一下testng基础教程,http://www.cnblogs.com/tobecrazy/p/4579414.html 昨天主要学习的是testng 的annotation基本用法和生命周 ...

  8. C++代码重构——从C global到C++ template

    在学数据结构的时候,我常有这样目标--写出能够最大程度复用的代码(算法正确,封装优秀).我常想--如何能在短时间内达成"算法正确,封装优秀"这样的目标.经过一段时间的摸索,我的结论 ...

  9. Bravebeart

    E - Bravebeart Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Sub ...

  10. Linux系统virtualbox + ubuntu + xshell 问题与注意事项

    序言:ubuntu闭源软件太多,一般不推荐使用:没钱可以使用centos.debian:有钱使用redhat 目前主流和常用的Linux版本主要有:1.Redhat 版本5.5和6.0最新:培训.学习 ...