2012-08-06 69 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。確定執行引擎時執行的操作並不重要,但主要是寫入時複製行爲通常會阻止複製。

相關問題