PHP 数组的拷贝是按值传递 or 按引用传递

时间:2022-08-22 23:13:54

在记忆中 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是按值传递还是按引用传递&quest;【转载】

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

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

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

  9. javascript数组操作&lpar;创建、元素删除、数组的拷贝&rpar;

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

随机推荐

  1. 边工作边刷题:70天一遍leetcode&colon; day 72

    Missing Range 要点:题简单,这类题的特点都是记录上一步的状态,比如这题是end 错误点: 三种情况:一是连续的,即和上一个end差1,而是中间只差1个数,没有'->',最后是大于1 ...

  2. java操作mysql中的编码问题解决

    要注意以下几点 1.在连接mysql数据库时 jdbc:mysql://localhost:3306/xiaonei?useUnicode=true&characterEncoding=utf ...

  3. (转载)记录函数 getStyle&lpar;&rpar; 获取元素 CSS 样式

    设置元素(element)的css属性值可以用element的style属性,例如要将element的背景色设置为黑色,可以这么做: element.style.backgroundColor = ' ...

  4. Bresenham算法的实现思路

    条件已知两个点的坐标p1(x0,y0),p2(x1,y1)要求画出这条直线 之后的e代表每次的误差积累,初始值为0,可以计算出斜率为k=dy/dx=(y0-y1)/(x0-x1) 1.x为阶跃步长(直 ...

  5. 毫秒转时间&lpar;java&period;js&rpar;

    SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss"); GregorianCalendar gc ...

  6. &lbrack;置顶&rsqb; Android系统移植与调试之-------&gt&semi;build&period;prop文件详细赏析

    小知识:什么是build.prop?   /system/build.prop 是一个属性文件,在Android系统中.prop文件很重要,记录了系统的设置和改变,类似於/etc中的文件.这个文件是如 ...

  7. 如何在 CentOS 7 上安装 Docker

    Docker 是一个开源工具,它可以让创建和管理 Linux 容器变得简单.容器就像是轻量级的虚拟机,并且可以以毫秒级的速度来启动或停止.Docker 帮助系统管理员和程序员在容器中开发应用程序,并且 ...

  8. 基于OpenGL编写一个简易的2D渲染框架-13 使用例子

    这是重构渲染器的最后一部分了,将会给出一个 demo,测试模板测试.裁剪测试.半透明排序等等: 上图是本次 demo 的效果图,中间的绿色图形展现的是模板测试. 模板测试 void init(Pass ...

  9. C&plus;&plus;基础学习-20120516

    1.一下是使用strcpy_s与strcpy的安全性比较 char szBuf[2] = {0}; strcpy_s(szBuf, 2, "12131");  //新的CRT函数  ...

  10. linux上安装Qt4&period;8&period;6&plus;QtCreator4&period;0&period;3

    一.Qt简介 Qt是1991年奇趣科技开发的一个跨平台的C++图形用户界面应用程序框架.它提供给应用程序开发者建立艺术级的图形用户界面所需的所有功能.Qt很容易扩展,并且允许真正地组件编程. 准备工作 ...