这不仅仅是关于 Smarty,我想大多数模板引擎都分配了变量。这更像是一个理论问题,而不是实际问题。我没有用例。
当您将一个大数组 $a 分配给另一个变量 $b 时,PHP 会发生什么? PHP复制数组?也许,只是也许,它在内部创建了一个指针。那么当你稍微改变 $a 时会发生什么? $b 不应更改,因为没有使用 & 来创建 $b。 PHP 只是将内存使用量加倍吗??
更具体地说:当您将一个大数组从 Controller ($a) 分配给您的模板引擎 ($tpl->vars['a'] ) 并在 View 中使用(extract 到 $a)? PHP 的内存只是增加了三倍吗??
现在如果我通过引用分配所有变量会发生什么?我很高兴我的观点能够将数组改回 Controller (无论如何我都不会回到那里)。如果变量在模板引擎 ($tpl->vars['a']) 中发生变化也没有问题。
通过引用分配所有变量是否更利于内存?性能更好?如果是这样:是否有可能出现奇怪的、不需要的副作用?
因为人们喜欢代码而不是故事:
// copies
$a = array( ... );
$tpl->assign('a', $a); // creates a copy (?) in $tpl->vars['a']
// pointer / by ref
$a = array( ... );
$tpl->assign_by_ref('a', $a); // creates a pointer in $tpl->vars['a'] because:
function assign_by_ref( $name, &$var ) {
$this->vars[$name] = $var; // voila pointer?
}
我很确定 PHP 不介意大数组、副本和克隆,但在性能和内存方面:哪个“更好”?
编辑
对于对象,所有这些都无关紧要。对象总是通过引用自动分配。由于物体很热,也许这是一个过时的问题,但我很好奇。
更新
所以 PHP 使用 copy on write... 喜欢它。对象总是指针。当您:
$a = new BigObject;
$b = $a; // pointer, right?
$b->updateSomethingInternally(); // $b is now changed > what about $a?
这是否触发了写时复制?还是 $a 和 $b 仍然相同(如 ===)?
编辑
我可以得出结论,仅仅为了节省内存,通过 ref 分配真的不值得吗? PHP 本身是否足够智能?
编辑
复制、克隆、引用等的有趣可视化:http://www.phpinsider.com/download/PHP5RefsExplained.pdf
最佳答案
PHP 使用一种称为写时复制的概念。 IE。如果您只是执行 $a = $b,PHP 不会将 $b 的整个值复制到 $a。它只会创建某种指针。 (更准确地说,$a 和 $b 将指向相同的 zval,并且它的 refcount 将增加。)
现在,如果 $a 或 $b 被修改,则该值显然不能再共享,必须复制。
因此,除非您不在模板代码中修改数组,否则不会进行任何复制。
一些进一步的说明:
谨防通过盲目插入引用来优化您的代码。通常它们会产生与您预期相反的效果。解释原因的示例:
$a = SOMETHING_BIG; // $a points to a zval with refcount 1 and is_ref 0
$b = $a; // $a and $b both point to a zval with refcount 2 and is_ref 0
$c =& $a; // Now we have a problem: $c can't just point to the same zval
// anymore, because that zval has is_ref to 0, but we need one
// with is_ref 1. So The zval gets copied. You now have $b
// pointing to one zval with refcount 1 and is_ref 0 and $a and
// $c pointing to another one with refcount 2 and is_ref 1
所以与你想要的相反的事情发生了。您实际上不是在节省内存,而是在分配额外的内存。通常很难判断添加引用会使它变得更好还是更坏,因为通常很难跟踪指向一个 zval 的所有不同变量(它通常不像看起来那么容易,只要看看 debug_zval_dump 的示例)功能。因此,真正了解引用是否对性能有益的唯一安全方法是实际分析这两种变体。
这只是对该主题的简短介绍。您可以在 blog post by Sara Golemon with the porvoking title "You're being lied to" 中找到对该主题的更深入分析。 .
关于php - Smarty(和其他 tpl ngins): assign and assign_by_ref,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5794746/
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
我需要一些关于TDD概念的帮助。假设我有以下代码defexecute(command)casecommandwhen"c"create_new_characterwhen"i"display_inventoryendenddefcreate_new_character#dostufftocreatenewcharacterenddefdisplay_inventory#dostufftodisplayinventoryend现在我不确定要为什么编写单元测试。如果我为execute方法编写单元测试,那不是几乎涵盖了我对create_new_character和display_invent
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
我已经搜索过这个问题的答案,但没有成功,有一个类似的问题,但答案在这种情况下不起作用,它按数字项目排序。SimilarQuestion-Thatdidnotwork我正在尝试使用ruby的sort_by对一个项目进行降序排序和另一个升序排序。我只能找到一个。代码如下:#PrimarysortLastNameDescending,withtiesbrokenbysortingAreaofinterest.people=people.sort_by{|a|[a.last_name,a.area_interest]}任何指导肯定会有所帮助。示例数据:输入罗素,逻辑欧拉,图论伽罗瓦,抽象代
在我的Controller中,我得到了按类别分组的所有Extras:defindex@categories=Extra.all.group_by(&:category)end结果类似于哈希数组:{#=>[#,#=>[#,#]}我想按类别“排序”列而不是id排序,它应该如下所示:{#=>[#,#=>[#,#]}当我尝试时:defindex@categories=Extra.all.group_by(&:category).sort_by{|s|s[:sort]}end我得到“没有将符号隐式转换为整数”。那是因为我在“sort_by”中使用了一个符号吗? 最佳答
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我来自C、php和bash背景,很容易学习,因为它们都有相同的C结构,我可以将其与我已经知道的联系起来。然后2年前我学了Python并且学得很好,Python对我来说比Ruby更容易学。然后从去年开始,我一直在尝试学习Ruby,然后是Rails,我承认,直到现在我还是学不会,讽刺的是那些打着简单易学的烙印,但是对于我这样一个老练的程序员来说,我只是无法将它
我在Rails模型中有两列相互关联:Article.bodyArticle.body_updated_on每次Article.body更新时,我想将Article.body_updated_on更改为Time.now。如果任何其他字段已更新,则无需进行任何操作。 最佳答案 只需在将回调保存到您的文章模型之前添加classArticle 关于ruby-on-rails-RubyonRails,在更新其他列值时更改列值,我们在StackOverflow上找到一个类似的问题:
使用RubyonRails,我使用给定的增量(例如每30分钟)用时间填充“选择”。目前我正在YAML文件中写出所有的可能性,但我觉得有一种更巧妙的方法。我想我想提供一个开始时间、一个结束时间、一个增量,并且目前只提供一个名为“关闭”的选项(想想“business_hours”)。所以,我的选择可能会显示:'Closed'5:00am5:30am6:00am...[allthewayto]...11:30pm谁能想出更好的方法,或者只是将它们全部“拼写”出来的最佳方法? 最佳答案 此答案基于@emh的答案。defcreate_hour
例如:options={fight:true,use_item:false,run_away:false,save_game:false}我想要一个计算结果为true的bool表达式,当且仅当:fight为true,其余为false(如上图所示)。我可以一起解决这个问题,但我正在努力训练自己编写更优雅的ruby。谢谢!编辑:黑客是:(options[:fight]==true&&options.delete(:fight).values.all{|x|!x}) 最佳答案 假设所有值都是严格的bool值,它很简单:options=