php 返回引用的疑问

2016-11-16 22:49:30 +08:00
 silenceeeee
class a{

    public $a = 5;

}

function &load_class(){

    static $_classes = array();
    
    if (!isset($_classes['a'])){
    
        $_classes['a'] = new a();
        
    }
    return $_classes['a'];
    
}

$obj = &load_class();

echo $obj->a;

$obj->a = 1;

$obj2 = &load_class();

echo $obj2->a;

echo PHP_EOL;

exit;

这段代码为什么会输出: 51 而不是: 55 ?

3336 次点击
所在节点    PHP
32 条回复
jarlyyn
2016-11-16 23:10:10 +08:00
因为$obj2==$obj
AbrahamGreyson
2016-11-16 23:20:31 +08:00
考察的就是那个 static 关键字,翻文档去吧
eoo
2016-11-16 23:39:44 +08:00
屎一样的代码。。。
Sunyanzi
2016-11-16 23:54:51 +08:00
这事情跟返回引用其实一点关系都没有 ... 你去掉这段程序里所有的 & 依然可以得到一样的结果 ...

我试着改一下这个代码看看会不会看起来更清晰 ...

```php
<?php
class a { public $a = 5; }

function load_class(){
static $_c = [];

if ( ! isset( $_c['a'] ) ) {
echo 2;
$_c['a'] = new a();
}
return $_c['a'];
}

$obj = load_class();
echo $obj->a;
$obj->a = 1;
$obj2 = load_class();
echo $obj2->a, load_class()->a, PHP_EOL;

```

假装支持 markdown ... 能明白这段程序为什么输出 2511 么 ..?

如果实在想不明白 ... 看这里 http://php.net/manual/en/language.oop5.static.php ...
shell92
2016-11-17 00:35:09 +08:00
看到 php 就头大
shell92
2016-11-17 00:36:27 +08:00
。。。。。
shell92
2016-11-17 00:39:36 +08:00
这个应该有!
haiyang416
2016-11-17 00:41:15 +08:00
有必要用这么脏的代码把自己绕进去么。。
silenceeeee
2016-11-17 06:54:20 +08:00
@eoo 你这种回答跟屎有什么两样
silenceeeee
2016-11-17 07:46:04 +08:00
各位 统一回复下 是我逗逼了
我是理解 static 的 脑子短路了 一直把输出结果想成了 55 而在想为什么不输出 51 其实它本来就输出的 51
silenceeeee
2016-11-17 08:02:46 +08:00
@haiyang416 说真的 我并不觉得这个代码混乱 这是 CI 框架中的一个方法 只是 我为了测试 把我不需要的代码去掉了 应该不难看出 这个方法(被我去掉一部分代码之前)本来是用注册表模式和单例结合起来返回一个类的实例 你觉得哪里不太好 可以讲出来探讨探讨啊 ~
silenceeeee
2016-11-17 08:05:15 +08:00
@Sunyanzi 这个看下我 10 楼的回复
silenceeeee
2016-11-17 08:09:19 +08:00
@Sunyanzi 另外 在顺带看你发的 PHP 手册链接时 又看到一个内容 不太理解 你看能否解释下
http://php.net/manual/zh/language.variables.scope.php 这个页面的 "全局和静态变量的引用" 小节里面的代码:
```
<?php
function test_global_ref() {
global $obj;
$obj = &new stdclass;
}

function test_global_noref() {
global $obj;
$obj = new stdclass;
}

test_global_ref();
var_dump($obj);
test_global_noref();
var_dump($obj);
```
为啥会输出:
NULL
object(stdClass)(0) {
}
按我理解的话 应该都输出 object(stdClass)(0) {}才对啊
silenceeeee
2016-11-17 08:27:01 +08:00
对 13 楼作如下补充:
13 楼的问题或许可以直接描述为:
$a = new stdclass;
$b = &new stdclass;
这两种生成对象的方式有什么本质上的区别
感觉 php 的引用概念好模糊 C 的就相对清晰
millson
2016-11-17 09:41:32 +08:00
static 在 php 中还是很常用的
Sunyanzi
2016-11-17 10:09:32 +08:00
@silenceeeee 你要知道 Assigning the return value of new by reference 已经不复存在了 ...

也就是说这是段过时的代码 ... 为什么这么表现手册上已经说的很清楚了 ... 四个字历史遗留 ...

这段代码在 php5 全系列都会有报错提醒 ... 所以其实了解这个对你学习 php 没什么用处 ...

不过如果你要是想深入研究 php 的话我也可以解释给你 ... 不过不确定你是否能听懂就是了 ...
silenceeeee
2016-11-17 11:09:16 +08:00
@Sunyanzi 以上你解释的这些其实我都知道的
关于函数返回引用值在 PHP5 中的变更;
关于这段代码是过时的代码;
我觉得这个问题这样打字不太好描述 同样 你给我解释可能也不太好描述 另外 我有点 C 基础 有指针的概念 如果你方便的话 我还是很希望你能跟我解释下的
haiyang416
2016-11-17 11:44:37 +08:00
@silenceeeee PHP 的引用和指针式两码事,不要和指针联系起来。我觉得只要简单的记住不要使用 & 来 rebind 不在 scope 内的 reference 就行。 test_global_ref 中 global 申明的引用 $obj 不在 test_global_ref 的 scope 内。

另外, 13 楼的代码在 Ubuntu14.04 PHP 5.5.9 上没有任何错误提示,运行结果和示例中的一致。
silenceeeee
2016-11-17 11:56:52 +08:00
@haiyang416 这个问题打算到此为止 可能像你说的 只能先避免这样的问题吧
我个人觉得 PHP 官方文档不足以解释这个问题了 要真的弄明白它 可能看 PHP 的源码比较靠谱

总之 谢谢大家的回复!
Sunyanzi
2016-11-17 12:10:07 +08:00
@haiyang416 php 的引用确实和指针是两码事这点没错 ... 其他完全不是你说的这样 ...

不过既然问题都结了我也就懒得再解释了 ... 另外你确定下开了 E_DEPRECATED 级别的报错 ...

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/321049

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX