我又来了,关于函数数组里面怎么创建新的键值问题

2017-05-08 19:41:49 +08:00
 543400
<?php

function demoArray(){

return array(
"a"="我是 a",
"b"="我是 b",

);

};

$aa=demoArray();
echo $aa["a"];
echo '---------------------';

/*我查了 PHP 的官方文档,没有找到对这种间接调用数组的方式做出详细创建数组的方法,求大神解答

*/














?>
2194 次点击
所在节点    PHP
28 条回复
543400
2017-05-08 19:45:06 +08:00
顺便问一下 为啥代码没高亮 @ω@
noark9
2017-05-08 21:25:13 +08:00
return array(
"a"=>"我是 a",
"b"=>"我是 b",

);

不是应该这样?难道 run 的时候没提示语法错误?
543400
2017-05-08 21:31:38 +08:00
@noark9 能讲解你这种方法怎么输出数组吗?
543400
2017-05-08 21:47:19 +08:00
补充一下 刚试了一下 unset()函数居然也失效了,不知道是不是我方法不对

unset( demoArray()["a"] );

这一段失效,不能删除
543400
2017-05-08 22:04:47 +08:00
<?php

function demoArray(){

return array(
"a"=>"我是 a",
"b"=>"我是 b",

);

};

unset( demoArray()["a"] );

$aa=demoArray();
echo $aa["a"];
echo '---------------------';

/*我查了 PHP 的官方文档,没有找到对这种间接调用数组的方式做出详细创建数组的方法,求大神解答

*/


?>
noark9
2017-05-09 14:32:28 +08:00
每次调用 demoArray 方法都会返回一个独立的数组对象,那你这里 unset( demoArray()["a"] ); 做 unset 跟下面 $aa=demoArray(); 所获取到的数组对象半毛钱关系都没有啊
以及你的问题很不清晰,“间接调用数组的方式做出详细创建数组的方法” 是什么意思
543400
2017-05-09 17:18:39 +08:00
@noark9 我的问题已经很清晰 我这个 demoArray() 用的是间接调用数组方法 但是不清楚这类方法怎么创建键值。 另外你不方便回复我上一个问你的问题?



return array(
"a"=>"我是 a",
"b"=>"我是 b",

);

不是应该这样?难道 run 的时候没提示语法错误?


这是你的回答,我的追问是"能讲解你这种方法怎么输出数组吗?"



"每次调用 demoArray 方法都会返回一个独立的数组对象,那你这里 unset( demoArray()["a"] ); 做 unset 跟下面 $aa=demoArray(); 所获取到的数组对象半毛钱关系都没有啊 " 可以讲清楚你这句话的意思吗??

我这段代码的意思是删除了"a"键值,但是无效,所以把它贴出来,是为了寻找我的 unset()函数失效的原因

$aa=demoArray(); 这种就是间接调用数组的方式,很抱歉,请重新翻看 php 文档。
543400
2017-05-09 17:22:09 +08:00
@noark9 很抱歉,要是我的问题让你脾气很暴躁或者没耐心,请拒绝回答,谢谢
543400
2017-05-10 22:45:04 +08:00
找到问题所在了,现在把解决方法贴出来,避免更多的人踩坑.

function demoArray() 是内部函数,外部要调用,创建,删除数组的话,首先要把内部函数改成全局变量才行,直接用 global 就可以解决这个问题了

global 之前先要实例化,

$bbb=demoArray() ;
global $bbb;
noark9
2017-05-11 12:01:49 +08:00
你代码里面,每次 demoArray() 实际上是创建了一个新的数组出来,也就是你 unset(demoArray()['a ‘]) 和下面 echo $aa['a'] 是两个东西
你把 unset 放在 $aa = demoArray() 后面,就有效了
上一个问题也没有拒绝回答,你说不输出,那么你原来代码用的是 = 不是语法有错么,原文问题没有提到 unset 的问题嘛,后面才加的
以及,问题,什么是间接调用数组,没明白这个话,从你代码上看,就是一个函数返回了一个数组
543400
2017-05-11 13:29:59 +08:00
@noark9 https://www.rockey1997.com/v2ex/%E5%9B%BE%E5%83%8F%20001.png
https://www.rockey1997.com/v2ex/%E5%9B%BE%E5%83%8F%20002.png

我讲的是不方便回答,没说你拒绝,我最后说拒绝的意思是给你台阶,你不懂就不要乱回答.这只会浪费双方的时间.

https://www.rockey1997.com/v2ex/%E5%9B%BE%E5%83%8F%20003.png
https://www.rockey1997.com/v2ex/%E5%9B%BE%E5%83%8F%20004.png

这是你所说的" 你代码里面,每次 demoArray() 实际上是创建了一个新的数组出来,也就是你 unset(demoArray()['a ‘]) 和下面 echo $aa['a'] 是两个东西
你把 unset 放在 $aa = demoArray() 后面,就有效了 "

打脸的事情一次就够,请不要多次.不懂就不要装懂,不懂就不要乱回答,谢谢
noark9
2017-05-11 21:19:36 +08:00
我说的是把 unset($aa['a']) 放到 $aa = demoArray() 下面
另外 demoArray() 函数每次返回确实都是一个独立的数组对象,所以你使用 unset(demoArray()['a']) 是没用的

unset(demoArray()['a']); 这行代码,本质上你可以认为解释器做了下面的操作

$tmp = demoArray();
unset($tmp);

---------------分割线,也就是说你的程序本质上变成下面的样子
function demoArray(){

return array(
"a"=>"我是 a",
"b"=>"我是 b",

);

};


$tmp = demoArray(); // 这里原来是这样的 unset( demoArray()["a"] );
unset($tmp);

$aa=demoArray();
echo $aa["a"];
---------------分割线

所以我说你 unset(demoArray()['a']) 和下面 $aa = demoArray(); 所操作的是两个独立的数组

你所说的间接引用数组,看了你发的文档才知道-,-原来以前的 php 这么二,函数返回值必须要用临时变量保存,不能直接使用,你那中文文档我没见过,这么翻译也很诡异

其次,不用说打脸不打脸,台阶不台阶,大家讨论问题,淡定点
noark9
2017-05-11 22:26:20 +08:00
@543400
最近刚好在研究 PHP 内存管理方面的问题,但是如果是 C 就好了,可以很容易把内存地址打印出来,PHP 没有这么个东西来做,但是 PHP 提供了查看变量内存引用计数的函数 debug_zval_dump,配合你的代码做下分析

// 上半部分代码不变
function demoArray(){

return array(
"a"=>"我是 a",
"b"=>"我是 b",

);

};
// 把你代码下面改一下改成这样
echo "\nS.1 -----------------------\n";
debug_zval_dump(demoArray());
unset( demoArray()["a"] );
debug_zval_dump(demoArray());

echo "\nS.2 -----------------------\n";
$aa=demoArray();
debug_zval_dump(demoArray());
debug_zval_dump($aa);

echo "\nS.3 -----------------------\n";
unset($aa['a']);
debug_zval_dump(demoArray());
debug_zval_dump($aa);

对应下面的输出,下面来细说具体,下面的 refcount 就是引用数量,代表有多少个变量引用着这个变量,但是要注意的是 debug_zval_dump 函数自身会对变量产生一个引用,也就是真实的引用数量实际上是下面的数字 -1,如果 refcount - 1 = 0 了说明上下文代码中没有引用到这个变量,在 debug_zval_dump 调用结束后,他的内存就会被回收

S.1 -----------------------
代码是这样

echo "\nS.1 -----------------------\n";
debug_zval_dump(demoArray());
unset( demoArray()["a"] );
debug_zval_dump(demoArray());

输出是这样
array(2) refcount(1){
["a"]=>
string(8) "我是 a" refcount(2)
["b"]=>
string(8) "我是 b" refcount(2)
}
array(2) refcount(1){
["a"]=>
string(8) "我是 a" refcount(2)
["b"]=>
string(8) "我是 b" refcount(2)
}
这里,是用来比较 unset 对 demoArray() 的影响
可以看到 unset(demoArray()['a']) 对 demoArray() 函数的返回值没有任何的影响
也说明了每次 demoArray() 返回的结果是相互独立的
其中对于数组的 refcount = 1 是 debug_zval_dump 函数产生的,对于数组中两个元素的 refcount = 2 是数组本身对数组中变量的引用和 debug_zval_dump 函数对数组两个元素的引用

S.2 -----------------------
代码是这样

echo "\nS.2 -----------------------\n";
$aa=demoArray();
debug_zval_dump(demoArray());
debug_zval_dump($aa);

输出是这样

array(2) refcount(1){
["a"]=>
string(8) "我是 a" refcount(3)
["b"]=>
string(8) "我是 b" refcount(3)
}
array(2) refcount(2){
["a"]=>
string(8) "我是 a" refcount(2)
["b"]=>
string(8) "我是 b" refcount(2)
}
这里是看使用 $aa = demoArray() 对引用计数的影响
第一组结果:数组的引用数量还是 1 证明只有 debug_zval_dump 函数对其引用了,但是里面的数组元素的引用数变成了 3 这是因为除了第一步中说到的 debug_zval_dump() 函数,和 demoArray() 返回的数组本身对这两个元素进行了引用,还有赋值以后 $aa 这个数组,对这两个元素进行了引用( PHP 是写时复制,也就是说,在不改变变量的情况下,PHP 并不会真实的复制变量,而是对原来变量的引用计数 +1,等到真实的发生读写的时候,才会创建新的变量)
第二组结果:对于数组本身,那就是 $aa 这个变量和 debug_zval_dump 函数对其引用,所以数组的引用数是 2,但是为什么元素的引用数是 1 呢?之前直接 debug_zval_dump 输出的为什么会更多呢?因为 debug_zval_dump 输出后,没有变量接收 debug_zval_dump(demoArray()); 这里 demoArray() 的返回值(没有变量引用 debug_zval_dump 函数里面 demoArray() 调用的结果)所以,这里引用计数变成 2,也就是数组 $aa 和 debug_zval_dump 分别对数组和数组里面的元素进行引用

S.3 -----------------------
代码是这样

echo "\nS.3 -----------------------\n";
unset($aa['a']);
debug_zval_dump(demoArray());
debug_zval_dump($aa);

输出是这样

array(2) refcount(1){
["a"]=>
string(8) "我是 a" refcount(2)
["b"]=>
string(8) "我是 b" refcount(3)
}
array(1) refcount(2){
["b"]=>
string(8) "我是 b" refcount(2)
}
这里是看 unset($aa['a']) 对引用计数的影响
在进行了 unset($aa['a']) 之后
第一组数据,直接输出 debug_zval_dump(demoArray()); 的结果,和 S2 中接近,但是数组中 a 元素的引用变成了 2,也就是说明 unset 有效果了,引用数组中的 a 元素的变量少了一个
第二组数据也就是 $aa 的引用情况,和预想的相同,a 没了,b 不变

---------------------

总结---------------------------------------

1. 上面三组输出,每一组 debug_zval_dump(demoArray()); 的输出结果都是一样的,可以侧面证明,每次 demoArray() 返回的数组,实际上都是独立的一个数组
2. 使用 $aa 变量存储了 demoArray() 返回的数组后,debug_zval_dump(demoArray()); 数组的引用计数器并未增加,证明 $aa 保存的数组和 demoArray() 返回的数组并没有关系
但是数组中元素的引用计数器变化证明,使用 $aa 存储了 demoArray() 返回的数组后,可以认为 $aa 保存数组的元素
3. 使用 unset($aa['a']) 后,数组中元素引用计数器变化,也证明了在这个时候 $aa 和 demoArray() 返回的数组是没关系的

撒花完结~~~~~~

补充下,我不是大神,大家一起交流学习才能提高,因为近期在写 php 的项目,很多经验是在使用其他语言开发的时候带过来的,但是基础概念是相通的,你说的那个参考文档没看过,因为在我用过的语言没有遇到过需要先使用临时变量获取函数结果(当然你说了我懒得去查这是个什么概念是我的锅),再使用结果的情况(我从 PHP 5.6 开始使用,去年升级公司服务器到 PHP7 就更没接触过了),这里涉及到了内存管理的一些知识,如果是 C 可以不用这么复杂的解释,直接打印内存地址就可以了
noark9
2017-05-11 22:29:47 +08:00
@543400
我所说的 “每次 demoArray() 实际上是创建了一个新的数组出来,也就是你 unset(demoArray()['a ‘]) 和下面 echo $aa['a'] 是两个东西” 这句话背后的东西,也就是上面所说的东西的结果
另外从感性上理解,如果能使用 unset(demoArray()['a']) 把 demoArray() 返回的数组都改变了,那么函数的调用就会变得不可信任 + 难以维护,所以一般情况下,我们很少使用全局变量去操控函数内的变化
hzw94
2017-05-11 23:38:21 +08:00
我怎么觉得, @noark9 是在自然的回答楼主的问题,不知道怎么就引爆了 @543400 楼主。
miaotaizi
2017-05-12 09:17:10 +08:00
@hzw94 因为楼主觉得弱鸡根本就没理解楼主说的是啥, 然后就 boooooooooooom!
noark9
2017-05-12 09:34:53 +08:00
@hzw94 😂😂😂
WytheHuang
2017-05-12 10:32:48 +08:00
莫名刺激楼主 G 点...哈哈哈瞬间爆炸。我觉得 @noark9 回答问题很好,又没有喷,也没有嘲讽。
543400
2017-05-12 11:16:07 +08:00
@noark9 信息量太大 我等等操作一遍试试看,不过打这么多字,辛苦你了,谢谢。
@hzw94
@miaotaizi
@WytheHuang

非常好,之前发这个问题一直没人回答,只有我爆炸了才有人吃瓜看热闹的过来水回复。

主要是一开始 return array()这段我看不懂是什么意思,之后追问却不正面回答我的问题,让我感觉这是来寻乐浪费我时间。而我一直强调 php 文档里面有这段数组间接引用,结果别人一直在否认却自己不去查。。。。。。能不气吗?

另外补充一点,用的文档是最新 5 月份的,因为官方的文档没有语法高亮,阅读起来有点枯燥,所以用第三方美化版,里面的翻译内容基本都一样,都是翻译起来很诡异。

最后因为我没有核验回复的信息,信息量太大我需要消化,但是我昨晚在看面相对象的时候,注意到这种间接引用数组的方式应该是为面向对象准备,不然平时谁也不会心态蹦到用这种方式增加工作量。再者 php5.5 增加这种方式,应该也是有用武之地。

然后我爆炸之后反而有人回复我了,搞不懂这种吃瓜心态。
noark9
2017-05-12 11:39:44 +08:00
@543400 并不是你爆炸我才接着回复,而是我发现你对这个问题理解上不太对,想把问题讨论清楚而已
看了文档所谓间接引用,原文用的词叫 dereferencing 意思也就说,函数返回的数组值,在 php 5.5 以前只是地址,并不能直接使用,在 php 5.5 后解释器自动的做了一次解除引用( reference 在有内存管理的语言里面一般叫引用,其实就是通过传递地址来传递变量或是对象,dereference 就是解除传递来地址的引用,变成实际可用的值或者对象)但是呢,实际上 php 5.5 以前必须这么使用,个人理解应该是解析器没办法去做这个操作(解析器开发者的锅)所以并没有什么用武之地,这只能算是一种语法糖
其次,我没有否仍你所说的东西,所谓间接引用确实没听过,这个问题本质对我来说就是函数返回了一个数组对象,这是长时间开发得到的经验
另外建议楼主找本系统点的入门书去学习,文档并不会教你怎么编程,只是告诉你有什么 API 怎么使用,就像有人给了你一堆积木,但是不告诉你怎么去建造大楼一样

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

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

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

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

© 2021 V2EX