2012-10-19 28 views
7

Đầu tiên, xin lỗi cho câu hỏi ngu ngốc, nhưng tôi đã đọc một bài báo trong php.net và tôi không thể hiểu chính xác nó nói gì.Phân công đối tượng trong PHP

<?php 
class SimpleClass 
{ 
    // property declaration 
    public $var = 'a default value'; 

    // method declaration 
    public function displayVar() { 
     echo $this->var; 
    } 
} 
?> 



<?php 

$instance = new SimpleClass(); 

$assigned = $instance; 
$reference =& $instance; 

$instance->var = '$assigned will have this value'; 

$instance = null; // $instance and $reference become null 

var_dump($instance); 
var_dump($reference); 
var_dump($assigned); 
?> 

Và đây kết quả đầu ra này:

NULL 
NULL 
object(SimpleClass)#1 (1) { 
    ["var"]=> 
    string(30) "$assigned will have this value" 
} 

$ dụ và $ tham khảo điểm đến cùng một nơi, tôi có được điều này và tôi hiểu lý do tại sao chúng tôi nhận NULL và NULL cho họ.

Nhưng khoảng $ được chỉ định thì sao? Nó cũng chỉ ra nơi mà $ instance được lưu trữ? Tại sao khi chúng tôi sử dụng $instance->var nó ảnh hưởng đến $ được chỉ định, nhưng khi chúng tôi đặt $ dụ thành rỗng, không có thay đổi nào với $ được chỉ định?

Tôi nghĩ rằng cả ba biến trỏ đến một nơi trong bộ nhớ, nhưng rõ ràng là tôi sai. Bạn có thể vui lòng giải thích cho tôi chính xác những gì xảy ra và $ được chỉ định là gì? Cảm ơn nhiều!

+0

Bạn có mã cho SimpleClass của mình? – user978122

+0

Các lớp học được tham chiếu trong hầu hết các trường hợp. Có vẻ như không có cấu trúc trong PHP mặc dù. –

+0

@AlvinWong, IIRC nó không đúng trước khi PHP5 –

Trả lời

6

$reference trỏ đến giá trị của $instance, mà chính nó là tham chiếu đến đối tượng. Vì vậy, khi bạn thay đổi giá trị chứa bởi $instance, $reference phản ánh thay đổi này.

$assigned, mặt khác, là một bản sao về giá trị của $instance, và độc lập chỉ ra các đối tượng chính nó mà $instance đề cập. Vì vậy, khi giá trị $instance được cập nhật để trỏ đến không có gì (ví dụ: null), $assigned không bị ảnh hưởng vì nó vẫn trỏ đến đối tượng và không quan tâm đến nội dung của $instance.

+0

Nếu chúng tôi gán một đối tượng cho một đối tượng khác, cả hai sẽ trỏ đến cùng một vị trí, cho đến khi giá trị của một thay đổi, phải ? – Dev

+1

No. Xem câu trả lời của tôi. –

4

Đặt $instance = null; không cập nhật $assigned vì không cập nhật dữ liệu tại vị trí nơi $instance điểm. Thay vào đó, sửa đổi con trỏ $instance để con trỏ không còn trỏ vào cùng một dữ liệu như $assigned.

+0

Nếu bạn thay thế null bằng bất kỳ giá trị nào, đầu ra sẽ vẫn giống nhau – Dev

0

Như bạn có thể thấy trong đoạn code

$ dụ = null; // $ instance và $ reference trở thành null

$ instance bây giờ đã trở thành bằng không, nhưng trước đó $ gán được thiết lập. do đó $ gán không nhận được giá trị null. $ reference nhận giá trị null bởi vì bạn đã tham chiếu nó với = & nó giữ giá trị của $ instance.

2

Đối tượng là một thực thể riêng biệt trong bộ nhớ có thể có 1 hoặc nhiều tham chiếu. Nếu nó có 0, nó là rác thu thập được.

Biến có chứa đối tượng thực sự là trỏ đến (đề cập đến) đối tượng đó. Vì vậy, khi bạn làm điều này:

$var1 = new Object(); 
$var2 = $var1; 

bạn chỉ cần tạo hai biến, trỏ đến cùng một đối tượng ($ var2 bản sao giá trị của $ var1, nhưng giá trị đó là tham chiếu đến đối tượng).

Nếu sau đó bạn viết, $var1 = null, bạn loại bỏ một tham chiếu đó, nhưng $ var2 vẫn trỏ đến đối tượng.

Nhà điều hành & thực sự trả về một tham chiếu đến biến đằng sau nó, vì vậy khi bạn viết

$var1 = &var2; 

sau đó $ var1 không trỏ đến đối tượng mà $ var2 điểm là tốt, nhưng $ var1 điểm tới $ var2. Vì vậy, khi bạn tạo $ var2 null, $ var1 trỏ tới cùng một giá trị rỗng đó.

+0

nếu chúng ta thay thế null thành giá trị khác, đầu ra sẽ giống nhau, nếu $ var1 = $ var và $ var được thay đổi, $ var1 cũng nên thay đổi vì cả hai đều giống nhau, trong trường hợp chúng ta sử dụng giá trị thay vì null. – Dev

+0

Không, chúng không trỏ đến giống nhau. –

+0

@Dev, bạn sai về điều đó. Bạn chỉ cần sao chép tài liệu tham khảo. Các tham chiếu thực sự được sao chép, vì vậy bạn có hai tham chiếu khác nhau trỏ đến một đối tượng. Bằng cách gán NULL cho $ var, bạn chỉ ghi đè lên một tham chiếu.Không phải đối tượng, cũng như các tham chiếu khác. – GolezTrol

2

Với dòng sau, chúng tôi bảo lưu một vị trí bộ nhớ, trong đó lưu trữ các đối tượng mới, và một con trỏ với nó, dán nhãn là $instance:

$instance = new SimpleClass(); 

Với dòng sau, chúng tôi tạo ra một tài liệu tham khảo đến con trỏ$instance, dán nhãn là $reference:

$reference =& $instance; 

với dòng sau, chúng tôi bảo lưu một m mới vị trí emory, dán nhãn là $assigned, khác nhau và indipendent từ trên, trong đó chúng ta lưu trữ một bản sao của con trỏ (không phải là đối tượng chính nó) tạo ở trên:

$assigned = $instance; 

Bằng cách đặt $instance để null, bạn sẽ không chỉ đặt con trỏ vào vị trí bộ nhớ chứa đối tượng thực tế, không phải đối tượng. Bất kỳ tham chiếu nào khác với nó (ví dụ: $reference) cũng sẽ không được đặt.

$assigned là bản sao của con trỏ (được lưu giữ trong một vị trí bộ nhớ khác), vẫn trỏ đến đối tượng thực tế.

Đây là lý do tại sao nó vẫn có thể được sử dụng để chỉ đối tượng thực tế.

Nhận xét này được tìm thấy trong tài liệu PHP đến để ủng hộ những gì ở trên nói:

<?php 
class A { 
    public $foo = 1; 
} 

$a = new A; 
$b = $a; 
$a->foo = 2; 
$a = NULL; 
echo $b->foo."\n"; // 2 

$c = new A; 
$d = &$c; 
$c->foo = 2; 
$c = NULL; 
echo $d->foo."\n"; // Notice: Trying to get property of non-object... 
?> 

Note

này đại diện cho một loại ngoại lệ khi nói về quản lý bộ nhớ. Trong khi sao chép một biến hoặc mảng được giải quyết chỉ bằng cách sử dụng các nhà điều hành =, với các đối tượng bạn sẽ explicitely sử dụng từ khóa clone, như đã nêu trong tài liệu PHP:

Một ngoại lệ cho việc giao thông thường bởi hành vi giá trị trong PHP xảy ra với các đối tượng, được gán theo tham chiếu trong PHP 5. Các đối tượng có thể được sao chép rõ ràng thông qua từ khóa nhân bản.

+0

Điều này rất khó hiểu. Không phải là $ instance và $ được gán cùng một vị trí bộ nhớ? Tôi nghĩ rằng với $ assign = $ instance chúng ta không đặt trước một vị trí bộ nhớ mới cho một bản sao của obect, nhưng đối với một con trỏ trỏ cùng một đối tượng và cùng một vị trí bộ nhớ với $ instance. Và chúng tôi không sao chép bất cứ điều gì - để sao chép đối tượng chúng ta nên sử dụng bản sao. Tôi có đúng không? – Faery

+0

Với $ assign = $ instance, chúng tôi thực sự đặt trước một vị trí bộ nhớ khác. Nó không phải là một con trỏ: nó là một địa chỉ bộ nhớ vật lý mới chỉ được gắn nhãn lại để thuận tiện cho bạn. –

+0

Đó là lý do tại sao tôi thấy tất cả các câu trả lời khác khó hiểu (xem phần Nhận xét của Dev). –

1

Câu trả lời ngắn, khi bạn tạo một tài liệu tham khảo sử dụng &, đây là những gì sẽ xảy ra:

$A ===+ 
     |===> [symbol table entry x] ====> (memory location) 
$B ===+ 

Khi bạn làm một nhiệm vụ bình thường sau đó:

$A ===+ 
     |===> [symbol table entry x] ===> (memory location) 
$B ===+         ^
              | 
$C =======> [symbol table entry y] ========+ 

Hãy bước thông qua mã:

$instance = new SimpleClass(); 

$assigned = $instance; 

Assertion:

$assigned === $instance 

Cả $assigned$instance tham khảo cùng một ví dụ của SimpleClass.

$reference =& $instance; 

Assertion:

$assigned === $instance === $reference 

Tất cả các biến tham khảo các ví dụ tương tự.

$instance->var = '$assigned will have this value'; 

Assertion:

$assigned === $instance === $reference 

Mặc dù tài sản của $instance được thay đổi, nó không ảnh hưởng đến tài liệu tham khảo.

$instance = null; // $instance and $reference become null 

$reference chỉ là một bí danh trong bảng biểu tượng, nó được giá trị giống như $instance; số lượng tham chiếu của phiên bản gốc (ví dụ: vị trí bộ nhớ) bị giảm xuống 1, biến số $assigned.

0

Nó thực sự đơn giản:

$a = 3; 
$b = $a; 
$c = &$a; 
$a = 0; 

var_dump($a); 
var_dump($b); 
var_dump($c); 

Kết quả sẽ là:

int(0) 
int(3) 
int(0) 

Vì vậy, nó không chỉ phân công đối tượng mà còn phân bình thường.

Các vấn đề liên quan