Heim Backend-Entwicklung PHP-Tutorial 谨慎使用PHP的引用类型详解_PHP教程

谨慎使用PHP的引用类型详解_PHP教程

Jul 13, 2016 pm 05:00 PM
php reference 使用 existieren 引用 von 类型 详解

谨慎使用PHP的引用 引用类型(Reference)在许多计算机语言中都被使用,而且是作为一个非常强大而实用的特性存在。它有类似指针(Pointer)的实现,却又有不同于指针的表现。

例如C++的引用,可以让不同变量指向同一个对象,同时又保有直接使用dot来获取对象成员,不用繁琐的使用dereference运算符(*)和Pointer to Member运算符(->)。Java和C#中就直接以引用为主要类型,尽量让开发人员避免使用指针。

PHP中也引入了引用类型,在对对象赋值传递上,基本可视为是同于Java/C#的引用传递(具体请见Objects and references)。但同时又支持在基础类型上通过引用运算符(&)来获得内容的引用。不过在实际的使用中,PHP的引用类型因为整个PHP设计结构而存在着许多的问题,使得在程序出现非预计的结果。

 引用变量可被赋予新的引用
在C++中,引用类型的变量只能在其定义时被赋予引用值,所以我们只要追踪到变量的定义处就可以知道变量是在操作哪个内容。

但是PHP不同,PHP里模糊了变量的定义,可以不定义就使用的变量。所以可以让变量被多次赋予引用值。

 

 代码如下 复制代码

$x = 21;
$y = 7;

$z = &$x;
$z = &$y;

var_dump($x,$y,$z);初次看起来,让人的感觉是$z变成了对$x的引用,然后让$z的内容变成了对$y的引用,也就是说$x和$z都成对$y的引用。但是实际输出结果是:

 代码如下 复制代码

int(21)
int(7)
int(7)从结果上看出,$x保持不变,只是$z被改变成了对$y的引用。相当于先unset了$z变量然后赋予了新值。

$z = &$x;
unset($z);
$z = &$y;这其实是比较合理逻辑,就比如下边的代码,我们并不是得到类似于“指向指针的指针(Pointer point to a Pointer)”那样的“引用引用的引用(Reference refer to a Referenece)”,只是多个引用到同一块内容的引用变量。

$x = 21;
$y = &$x;
$z = &$y

引用数组元素会让该元素变成引用类型
对于变量上取引用,并不会造成原变量类型的改变,但是如果取的是数组中的元素,却会让该元素也变成引用类型。

在看问题代码前,首先要指出的是:

 Array assignment always involves value copying. Use the reference operator to copy an array by reference.

也就是说PHP的数组赋值是copy而非引用,赋值过程会创建新的数组赋予被赋值的变量。在新变量上的数组操作并不会影响到原数组变量中的内容。

 代码如下 复制代码


$a = array(21, 7);
$b = $a;
$b[0] = 7;
var_dump($a);
echo '
';
var_dump($b);

//Output:
//array(2) { [0]=> int(21) [1]=> int(7) }
//array(2) { [0]=> int(7) [1]=> int(7) }下边我们再来看看如果引用数组中的元素,会有什么异常。


$a = array(21, 7);
$c = & $a[0];
$b = $a;
$b[0]= "21";
$b[1]= "7";

var_dump($a);
echo '
';
var_dump($b);
echo '
';
var_dump($c);
echo '
';

// Output:
// array(2) { [0]=> &string(2) "21" [1]=> int(7) }
// array(2) { [0]=> &string(2) "21" [1]=> string(1) "7" }
// string(2) "21"

代码中$b跟之前的只是简单的赋值,只是在之前多了一部取第一个元素的引用,但理应还是拷贝了一个新的数组。可是结果却是对$b的修改,同时也改变了$a的第一个元素,而第二个元素没有影响。

从输出中我们还看到了一个不寻常的地方,就是数组第一个元素的类型多一个‘&’符号。而这个正是取引用运算符。也就是说数组的第一个元素已经变成了引用类型。所以赋值时也是引用拷贝,而非值拷贝。

这个问题十分奇怪,在开发中也造成了许多不必要的困扰,原本以为拷贝出来的数组并没有跟原数组有关联,但是就因为这意外出现的引用类型,让我在操作时也影响到了原数组。

我也不清楚这算是PHP中的bug,还是有意如此设计。在网上找了很久也没有对该方便的相关解释,只有Float Middle的《PHP: References To Array Elements Are Risky》和 Symmetric Designs的《Problems w/accessing a PHP array by reference》里有谈到这个,但是也没有讲原因。

之后又在PHP的Bug Report中看到几篇有联系的报告(Bug6417, Bug7412, Bug15025, Bug20993)。有些说这是个Bug,而且已经在后边的版本被修复。具体我也没有明白,只能避免在数组上使用引用。

 更有趣的事情是,如果unset那些引用,只留下一个,那么数组元素又会变成不含有引用的正常类型。

 代码如下 复制代码

unset($b);
unset($c);
var_dump($a);
   
// Output:
//array(2) { [0]=> string(2) "21" [1]=> int(7) }

避免使用PHP的引用
这个其实这是PHP Array Manual里面提到的要注意的地方,最常发生在foreach的之中,希望通过引用来改变远数组的值(可参见该篇文章)。

其实想通过使用foreach配合引用来改变数组元素的值,主要是因为PHP的数组是Associative Array,这种数组“不定长度,索引可以不连续,可同时用字符串和整数当索引”,所以我们无法用for循环简单增加整数索引。

当然我们可以像下边的代码那样通过$key直接对数组元素改变值,但是这可能存在一定的效率问题。

 代码如下 复制代码
foreach ($array_var as $key => $value)
    $array_var [$key] = $newValue;

另一个常用的引用的地方是在函数调用中使用引用传递参数。其主要原因是希望通过这种方法让函数实现返回多个返回值。比如我们希望用一个表示指示函数是否在执行中出现error而导致返回值是无效的。

但是因为PHP的函数是可以返回不同的类型的,所以并不需要传入引用参数来作为表示。即使真的需要多个返回值,也可以通过返回“以字符串为主键的数组”作为解决方案,只不过可能需要在文档中指出每个元素都是对应那个结果。

 有一个比较好操作方式,应该是每当引用变量不再需要使用时,就即时对该变量使用unset让它切换与内容之间的联系。而且即使该变量不是引用类型,我们确认它不再被使用,对它调用unset也不会有什么问题。至少保证在之后对该变量重新赋值时,并不会影响到之前的结果。

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/631276.htmlTechArticle谨慎使用PHP的引用 引用类型(Reference)在许多计算机语言中都被使用,而且是作为一个非常强大而实用的特性存在。它有类似指针(Pointer)的实...
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heißer Artikel

R.E.P.O. Energiekristalle erklärten und was sie tun (gelber Kristall)
2 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
Repo: Wie man Teamkollegen wiederbelebt
4 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Abenteuer: Wie man riesige Samen bekommt
3 Wochen vor By 尊渡假赌尊渡假赌尊渡假赌

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

CakePHP-Projektkonfiguration CakePHP-Projektkonfiguration Sep 10, 2024 pm 05:25 PM

In diesem Kapitel werden wir die Umgebungsvariablen, die allgemeine Konfiguration, die Datenbankkonfiguration und die E-Mail-Konfiguration in CakePHP verstehen.

PHP 8.4 Installations- und Upgrade-Anleitung für Ubuntu und Debian PHP 8.4 Installations- und Upgrade-Anleitung für Ubuntu und Debian Dec 24, 2024 pm 04:42 PM

PHP 8.4 bringt mehrere neue Funktionen, Sicherheitsverbesserungen und Leistungsverbesserungen mit einer beträchtlichen Menge an veralteten und entfernten Funktionen. In dieser Anleitung wird erklärt, wie Sie PHP 8.4 installieren oder auf PHP 8.4 auf Ubuntu, Debian oder deren Derivaten aktualisieren. Obwohl es möglich ist, PHP aus dem Quellcode zu kompilieren, ist die Installation aus einem APT-Repository wie unten erläutert oft schneller und sicherer, da diese Repositorys in Zukunft die neuesten Fehlerbehebungen und Sicherheitsupdates bereitstellen.

CakePHP Datum und Uhrzeit CakePHP Datum und Uhrzeit Sep 10, 2024 pm 05:27 PM

Um in cakephp4 mit Datum und Uhrzeit zu arbeiten, verwenden wir die verfügbare FrozenTime-Klasse.

CakePHP-Datei hochladen CakePHP-Datei hochladen Sep 10, 2024 pm 05:27 PM

Um am Datei-Upload zu arbeiten, verwenden wir den Formular-Helfer. Hier ist ein Beispiel für den Datei-Upload.

CakePHP-Routing CakePHP-Routing Sep 10, 2024 pm 05:25 PM

In diesem Kapitel lernen wir die folgenden Themen im Zusammenhang mit dem Routing kennen.

Besprechen Sie CakePHP Besprechen Sie CakePHP Sep 10, 2024 pm 05:28 PM

CakePHP ist ein Open-Source-Framework für PHP. Es soll die Entwicklung, Bereitstellung und Wartung von Anwendungen erheblich vereinfachen. CakePHP basiert auf einer MVC-ähnlichen Architektur, die sowohl leistungsstark als auch leicht zu verstehen ist. Modelle, Ansichten und Controller gu

So richten Sie Visual Studio-Code (VS-Code) für die PHP-Entwicklung ein So richten Sie Visual Studio-Code (VS-Code) für die PHP-Entwicklung ein Dec 20, 2024 am 11:31 AM

Visual Studio Code, auch bekannt als VS Code, ist ein kostenloser Quellcode-Editor – oder eine integrierte Entwicklungsumgebung (IDE) –, die für alle gängigen Betriebssysteme verfügbar ist. Mit einer großen Sammlung von Erweiterungen für viele Programmiersprachen kann VS Code c

CakePHP erstellt Validatoren CakePHP erstellt Validatoren Sep 10, 2024 pm 05:26 PM

Der Validator kann durch Hinzufügen der folgenden zwei Zeilen im Controller erstellt werden.

See all articles