3

如果我用引用覆盖原始变量,内部会发生什么?
意思很糟糕,是否需要额外的时间或资源?

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

$db = db();
?>
4

4 回答 4

3

如果你使用

global $db;

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

然后它作为另一个变量存在(代表全局变量)。您最终尝试返回对该变量的引用:

return &$db;

但这不是引用返回。相反,您只需返回值。

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

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

你做的任何多余的事情都会花费额外的时间或资源。然而 PHP 有一个称为写时复制 (COW) 的优化,所以通常你不需要在这里太在意。PHP很好地消除了负担。

就您的代码中涉及的对象而言。只需这样更改:

<?php

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

?>

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

于 2012-08-06T12:42:59.803 回答
0

由于您的原始示例是语法错误,我认为这就是您想要写的:

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

如果您真的那么倾向于,您可以使用vulcan 逻辑反汇编程序运行您的脚本并获取操作码。唯一显着的区别是带有引用的版本使用 RETURN_BY_REF 和 ASSIGN_REF 操作码,而不是 RETURN 和 ASSIGN。确定引擎在执行时执行的操作并非易事,但主要是写时复制行为通常会阻止复制。

于 2012-08-06T14:33:46.363 回答
0

That is not the way you return by reference. You must declare the function like this:

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

You need not return objects by reference, the language specifies all objects are returned by reference automatically, and the manual also strongly recommends not to use the by reference operator for objects.

Is this what u actually mean:

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;
}

Usage:

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)
   ;
}
于 2012-08-06T12:52:07.370 回答
0

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

如果我没记错的话,当一个对象在 PHP 5 中返回时,即使你没有在它前面加上 (&),它也是通过引用返回的。(本人立场更正的对象不作为参考退回):

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

我从所有其他编程语言中知道,对象是通过引用传递/返回的,而本机数据类型是通过副本返回的。

在您的示例中,当您使用全局变量时,您已经在函数外部引用了该变量。不需要返回值,因为您已经覆盖了它。

于 2012-08-06T12:38:45.363 回答