2012-08-06 70 views
3

如果我用参考覆盖原始变量会发生什么?
含义是不好的,这是否需要额外的时间或资源?如果我用引用覆盖原始变量,内部会发生什么?

<?php 
function db(){ 
    global $db; 
    if(empty($db)) $db = new PDO('sqlite:/tmp/default.db3'); 
    return &$db; 
} 

$db = db(); 
?> 
+1

你*不*覆盖参考。也许你可以更好地制定你实际上不了解的参考回报? – hakre 2012-08-06 12:35:07

+0

在2012年使用php中的'global' - 它的不好的做法。 – voodoo417 2012-08-06 12:36:10

+2

确实有趣的问题。我认为这是完全不好的做法。只要保持理论。 (我几乎没有用我的upvotes推理,但这是需要的。) – Whisperity 2012-08-06 12:37:02

回答

0

它不应该消耗更多的资源,因为你要返回的对象总是小于对象的地址。

如果我没有弄错,在PHP 5中返回对象时,即使您不预先添加(&),它也会通过引用返回。 (我认错的对象没有被全球化志愿服务青年返回):

http://php.net/manual/en/language.references.return.php

我从对象通过返回的所有其它编程语言知道通过/通过复制参考和原始数据类型返回。

在你的例子中,当你使用全局变量时,你已经接受了函数之外的变量。由于您已经覆盖它,因此不需要返回值。

+2

这又是不正确的。对象不会被引用返回。你可以在这里的PHP手册中找到:[Objects and references](http://de.php.net/manual/language.oop5.references.php) – hakre 2012-08-06 12:39:54

+0

我说如果我没有弄错的话。我刚刚阅读了这个:http://php.net/manual/en/language.references.return.php – thedethfox 2012-08-06 12:44:40

+0

不,对象总是按值返回。但是它们的值是一个对象标识符。所以即使您复制了该值,您也只能复制标识符。你不能通过值来复制对象,因此实际上(这就是为什么有些人认为它必须是一个引用,但它不是),你只能[克隆](http://de.php.net/clone)它们。 – hakre 2012-08-06 12:47:23

3

如果使用

global $db; 

这将导入全局变量$db到本地范围。

然后存在另一个变量(表示全局变量)。你终于尝试一个参考返回变量:

return &$db; 

但这不是return by reference。相反,你只需返回值。

然后您在全局变量表上覆盖$db自己的值。这就是这里发生的一切。

是否需要额外的时间或资源?

您所做的一切多余花费额外的时间或资源。但是PHP有一个称为copy on write(COW)的优化,所以通常在这里你不需要太在意。 PHP非常好,可以减轻负担。

只要您的代码中涉及对象。只要这样改变它:

<?php 

$db = new PDO('sqlite:/tmp/default.db3'); 

?> 

然后将db对象传递到需要它的地方。保持简单,愚蠢。

0

这不是您通过参考返回的方式。 您必须声明是这样的功能:

function &return_by_ref() 
{ 
    $something=""; 
    return $something; 
} 

你不必引用返回对象,语言指定的所有对象都通过引用自动返回,手动也强烈建议不要通过对象引用运营商使用。

这是什么ü实际上意味着:

class DB{ 
    private function __construct(){} 
    public static $db=null; 
} 

function db($db) 
{ 
    if(!isset(DB::$db)) 
     DB::$db=new PDO('sqlite:/tmp/default.db3'); 
    return DB::$db; 
} 

用法:

function create_user() 
{ 
    db()->exec("INSERT INTO `users` SET `name`='John Doe'"); 
    return db()->lastInsertId(); 
} 

function get_users() 
{ 
    return db() 
     ->query("SELECT * FROM `users`") 
     ->fetchAll(PDO::FETCH_ASSOC) 
    ; 
} 
+0

正如Hakre正确指出的那样,文档实际上并没有说“语言指定的所有对象都是通过引用自动返回的”。虽然如果您尝试在没有通过引用传递的情况下修改函数中的对象变量,效果会非常相似,但实际上并不会修改该对象。 (您将丢失引用并且有一个新变量)传递给函数的值是对象的标识符,而不是对变量所在的内存空间的引用。 – williamvicary 2012-08-06 12:57:43

+0

你有任何证据吗?你知道有多个PHP实现(Zend,HipHop,Phalanger)吗?你知道这是一个可能的优化,如果它还不存在,它肯定会在未来?你知道在Exception的堆栈跟踪中,对于每个添加了不同修改(使调试变得痛苦)的每个函数,对象都会以最后修改状态出现? – 2012-08-06 13:37:15

+0

另外,您是否阅读了我的答案的第一行?该问题包含无效的PHP代码。虽然如此,但我无法回答关于无效PHP代码的PHP内部结构。 – 2012-08-06 13:38:34

0

因为你原来的例子是语法错误,我认为这是你想写什么:

function db(){ 
    static $db = null; 
    if ($db === null) { 
     $db = new PDO('sqlite:/tmp/default.db3'); 
    } 
    return $db; 
} 

如果你真的那么倾向于,你可以用vulcan logic disassembler运行你的脚本并获取操作码。唯一显着的区别是带引用的版本使用RETURN_BY_REF和ASSIGN_REF操作码而不是RETURN和ASSIGN。确定执行引擎时执行的操作并不重要,但主要是写入时复制行为通常会阻止复制。

相关问题