目次
ディスカッション(解決策)への返信

PHP変数参照に関する疑問

Jun 23, 2016 pm 02:04 PM

変数の参照と代入はしっかりできているつもりだったのですが、私の理解を完全に覆す以下の問題に遭遇しました

<?php   $str = 'WangChuanbo';  $s = &$str;  unset($str);  echo $s,'hello world';?>
ログイン後にコピー

その結果、$s を出力した後も Wangchuanbo のままでしたね。元の変数はすべてアンロード後も参照変数に値が残っていますか? ?


ディスカッション(解決策)への返信

張飛の姓は張飛、名は易徳です
つまり、張飛と張一徳は同一人物です
あなたは張飛を殺しましたが、あなたはただ張飛という名前を世界から消し去り、その人は今でも張一徳という名前で歩き回っています

張飛の名字は張飛、名は易徳です

つまり、張飛と張一徳は同一人物ということになります
あなたが殺した張飛、でもあなたは張飛という名前を世界から消し去っただけで、その人は今でも張一徳というタイトルで回っています

それは理にかなっていて、少しは理解できますが、まだ完全ではありません。 PHPの参照機構とCのポインタには違いがあると言われますが、本質的な違いが分かりません。

私は、これが参照と割り当てを理解する良い方法であると常に考えてきました。


Windows システムでは、
E ドライブ上のファイルをデスクトップにコピーすることは、どちらが変更されても、もう一方は変更されません。 . が変更されます; デスクトップにショートカットを作成すると、どちらが変更されても、もう一方も変更されます
これはまったく説明がつかないので、混乱します

参照の設定を解除するだけです。と変数の内容 php の

$s = &$str; のバインディングは
$s と $str の両方が同じ場所 C を指すことを意味します
設定を解除した後、$str は C を見つけることができません
別の例を挙げましょう
Small Zhang は聞きましたシャオ・リーは、宝は海の上にあると言います
シャオ・リーは記憶を失っていますが、シャオ・チャンは宝が海にあることをまだ知っていました

C++ では、参照とはメモリのアドレスさえも同じであることを意味します
最終的には、それは定数ポインタです

単純 C のポインタはメモリ内の特定のアドレスを指すと言われています。そのため、ポインタは演算に参加できます。PHP コードはコンパイルされません。マシンコードに組み込まれるため、メモリアドレスにアクセスするという話はありません

確かに、PHP の参照メカニズムは C のポインタと非常によく似ています。ポインタの動作を無視した場合、少なくともパフォーマンスは最高です。ポインタと同じです


まず、変数の設定を解除しても、それがメモリから消去されるわけではありません。 PHPのガベージコレクションはGCで完結!

参照の設定を解除すると、変数名と変数の内容の間のバインディングが解除されるだけです

$s = &$str; php では、これは

$s と $str の両方が同じ場所 C を指すことを意味します

設定解除後 $ Cは str では見つかりません

別の例を挙げましょう
シャオ・チャンはシャオ・リーが宝が海にあると言っているのを聞きました
シャオ・リーは記憶を失っていますが、シャオ・チャンは宝が海にあることをまだ知っています

C++ 、引用の意味 メモリアドレスさえ同じです
結局のところ、それは定数ポインタです

あなたの説明を受けて、私は実験しました

$str = 'WangChuanbo';$s = &$str;$s = 'new';echo $str;
ログイン後にコピー


参照変数が変更されているのは事実であり、元の変数はunset()関数を理解していないためです。Windowsシステムでファイルをコピーするということは理解できますか?デスクトップへの E ドライブは値の割り当てであり、どちらが変更されても、もう一方は変更されません。また、デスクトップに作成されたショートカットは、どちらが変更されても参照されます。修正されましたか?

4 階 franzhong の返信からの引用: 参照の設定を解除し、変数名と変数の内容を切断するだけです
PHP の $s = &$str; は
C++ では、参照はメモリ アドレスさえも意味します同じです

...

もちろん、このように理解することに固執する場合は、笑
Fドライブにfffフォルダーがあるので、右クリックして「送信 => デスクトップショートカット」をクリックします
それから名前を変更します それをaaa、doと呼んでくださいもう一度、名前を bbb に変更します
aaa を開いてその中に txt を作成し、次に bbb を開くとその中に txt があります
それはそういうことではないでしょうか


简单的说
C的指针 指向的是内存中特定的地址
C的指针 有个数据类型的概念,因此指针是可以参与运算的
php代码并没有给编译成机器码,所以没就访问内存地址一说
的确php的引用机制和C的指针极其相似,如果不计指针的运算,那么至少在表现上与指针是一样的

有两篇博文我读了几遍,发现每个人都有自己的见解,于是就想把这个问题搞透,
参考一: http://www.nowamagic.net/php/php_ReferenceOperator.php
很多人误解php中的引用跟C当中的指针一样,事实上并非如此,而且很大差别。C语言中的指针除了在数组传递过程中不用显式申明外,其他都需要使用*进行定义,而php中对于地址的指向(类似指针)功能不是由用户自己来实现的,是由Zend核心实现的,php中引用采用的是“写时拷贝”的原理,就是除非发生写操作,指向同一个地址的变量或者对象是不会被拷贝的

参考二、 http://blog.csdn.net/woods2001/article/details/7569099

发现越来越困惑了

6楼说的对 要理解这个你需要理解PHP的垃圾回收机制

PHP 的变量并不像C/C++一样 PHP的变量存储在ZVAL机构中 结构体定义如下
typedef struct _zval_struct zval;
...
struct _zval_struct {
/* Variable information */
zvalue_value value; /* value */
zend_uint refcount__gc;
zend_uchar type; /* active type */
zend_uchar is_ref__gc;
};
zval结构体中有四个字段,其含义分别为:

属性名 含义 默认值
refcount__gc 表示引用计数 1
is_ref__gc 表示是否为引用 0
value 存储变量的值
type 变量具体的类型

unset() 并不会直接销毁变量 只有当refcount=0时才会被PHP的垃圾回收机制回收

$a = 10;
xdebug_debug_zval('a');
//output: a: (refcount=1, is_ref=0)=10
$b = &$a;
xdebug_debug_zval('a');
//output: a: (refcount=2, is_ref=1)=10
$a = 20;
xdebug_debug_zval('a');
//output: a: (refcount=2, is_ref=1)=20
unset($b);
xdebug_debug_zval('a');
//output: a: (refcount=1, is_ref=0)=20


本帖将会 继续加分,希望大家踊跃发言, 百家争鸣,方才百花齐放

其实很多人在解释引用时都喜欢那php的底层实现来说事,其实这是不对的
解释要用浅显的道理,而非深层次的原理来说明。否则就是越说越乱
就像任何 C 语言书中都不会用汇编语言来解释指针,因为高层都还没明白,底层怎么能明白

php 的引用从表现上看,就如同指针一样。所以把它看成“指针”并无大碍
只是你不要把引用当做“指针”来运算就可以了

换一种方式来理解的话就是
指针是按门牌号码来进出商业街上的每家店铺,所以他可以明确的知道下一家在哪里
引用是按店铺的招牌来进出的,因此他并不能知道旁边的是谁
除此之外,两者的表现并无区别

学习了!

下面希望不要记错:
记忆中php的引用是+1机制,就是每当多一个引用计数器就+1,unset一个就-1
只要变量还有某个单元在使用(不为0),则有效的相关变量名仍然可用

关于这个知识点,我想说三个点:
第一:只有变量才可以有地址,值没有,函数中如果有变量前加&,必须传变量;

        $a=100;    function myfun(&a){ // &后面必须是变量,直接写100不行,必须把100赋给变量$a,写$a        $a++;        return $a;    }    echo myfun($a); //101,  如果写成myfun(100),是错误的
ログイン後にコピー

第二:使用UNSET()删除时,只删除 引用关系,并没有删除 值
    $a="aaaaaaaa";    $b=&$a;    unset($b);//unset($b),只删除引用关系,并没有删除值    echo $a; //aaaaaaaa
ログイン後にコピー

第三:如果重新给一个变量新的引用,引用关系发生改变;
    $a="aaaaaaaaa";    $c="ccccccccc";    $b=&$a;       $b=&$c;    var_dump($b);// string(9) "ccccccccc" 
ログイン後にコピー


在网上帮你找个图片 你看下

这个问题我也在问

私もこの質問をしています

どう理解できますか?

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットな記事タグ

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

11ベストPHP URLショートナースクリプト(無料およびプレミアム) 11ベストPHP URLショートナースクリプト(無料およびプレミアム) Mar 03, 2025 am 10:49 AM

11ベストPHP URLショートナースクリプト(無料およびプレミアム)

Instagram APIの紹介 Instagram APIの紹介 Mar 02, 2025 am 09:32 AM

Instagram APIの紹介

Laravelでフラッシュセッションデータを使用します Laravelでフラッシュセッションデータを使用します Mar 12, 2025 pm 05:08 PM

Laravelでフラッシュセッションデータを使用します

Laravelテストでの簡略化されたHTTP応答のモッキング Laravelテストでの簡略化されたHTTP応答のモッキング Mar 12, 2025 pm 05:09 PM

Laravelテストでの簡略化されたHTTP応答のモッキング

PHPのカール:REST APIでPHPカール拡張機能を使用する方法 PHPのカール:REST APIでPHPカール拡張機能を使用する方法 Mar 14, 2025 am 11:42 AM

PHPのカール:REST APIでPHPカール拡張機能を使用する方法

LaravelのバックエンドでReactアプリを構築する:パート2、React LaravelのバックエンドでReactアプリを構築する:パート2、React Mar 04, 2025 am 09:33 AM

LaravelのバックエンドでReactアプリを構築する:パート2、React

Codecanyonで12の最高のPHPチャットスクリプト Codecanyonで12の最高のPHPチャットスクリプト Mar 13, 2025 pm 12:08 PM

Codecanyonで12の最高のPHPチャットスクリプト

Laravelの通知 Laravelの通知 Mar 04, 2025 am 09:22 AM

Laravelの通知

See all articles