2011-06-21 36 views
5

Trong ví dụ bên dưới, tôi không hiểu tại sao localVariable đang được truy cập theo giá trị trong doSomethingWithObject. Điều gì làm cho chuyển đổi đó? Làm thế nào để bạn phân biệt giữa việc truy cập một biến theo giá trị và truy cập nó theo tham chiếu? Tôi muốn xem thêm các ví dụ liên quan nếu có thể.Truy cập các biến theo giá trị hoặc tham chiếu

Sau đây là trích đoạn từ số Blocks Programming Topics của Apple và hiển thị cách các biến mẫu được giữ lại trong các khối.

Nếu bạn sử dụng một khối trong việc thực hiện của một phương pháp, các quy tắc cho quản lý bộ nhớ của đối tượng biến dụ là tinh tế hơn:

  • Nếu bạn truy cập một biến Ví dụ tham khảo, self bị cản trở;
  • Nếu bạn truy cập một biến mẫu theo giá trị, biến đó sẽ được giữ lại.

Các ví dụ sau minh họa cho hai tình huống khác nhau:

dispatch_async(queue, ^{ 
    // instanceVariable is used by reference, self is retained 
    doSomethingWithObject(instanceVariable); 
}); 

id localVariable = instanceVariable; 
dispatch_async(queue, ^{ 
    // localVariable is used by value, localVariable is retained (not self) 
    doSomethingWithObject(localVariable); 
}); 

Trả lời

12

Đó là bởi vì khi bạn truy cập vào một biến Ví dụ trực tiếp, trình biên dịch (nhiều hơn hoặc ít hơn) dịch đó vào một tra cứu viên struct. Vì vậy:

[ivar doSomething]; 

trở thành

[self->ivar doSomething]; 

self là cần thiết, self phải được giữ lại. Tuy nhiên, khi bạn sao chép giá trị con trỏ vào một biến mới, bạn biết còn cần cấu trúc self để biết giá trị con trỏ là gì và do đó self không cần giữ lại, vì giá trị con trỏ có thể được sao chép khỏi ngăn xếp const. Điều đó không thể xảy ra với một biến cá thể (vì ivar có thể thay đổi giữa khi khối được tạo và khi khối được thực thi).


Làm rõ:

  • một khối phải giữ lại tất cả các đối tượng mà nó tham chiếu trong nội bộ để đảm bảo rằng những đối tượng sẽ tiếp tục tồn tại trong suốt vòng đời của khối.
  • khi bạn truy cập trực tiếp mã vạch, bạn thực sự chỉ cần tìm kiếm thành viên của cấu trúc (vì đối tượng Object-C thực sự chỉ là cấu trúc)
  • tra cứu thành viên của cấu trúc có nghĩa là bạn phải có cấu trúc
  • do đó, một khối sẽ giữ nguyên cấu trúc (trong trường hợp này là self) để tra cứu sẽ luôn thành công. Nếu nó không làm điều này, thì self có khả năng có thể được giải quyết trong tương lai, và bây giờ việc tra cứu cấu trúc sẽ gây ra một truy cập xấu (rất có thể) và ứng dụng của bạn sẽ sụp đổ.
  • cách khác, bạn có thể tạo một con trỏ đối tượng mới cục bộ trong khung ngăn xếp hiện tại.Điểm mấu chốt của điều này là bạn không còn phải giữ lại self, bởi vì self không còn liên quan đến việc truy xuất địa chỉ của đối tượng được đề cập
  • tất nhiên, đối tượng được tham chiếu bởi biến cục bộ sẽ được giữ lại để đảm bảo rằng nó tồn tại cho suốt đời của khối.
  • sử dụng cụm từ "theo giá trị" và "theo tham chiếu" ở đây là hoàn toàn không chính xác. Các đối tượng trong Objective-C luôn được truyền theo tham chiếu, vì chúng ta luôn luôn là các con trỏ đi qua. Bạn không thể chuyển một đối tượng theo giá trị trong Mục tiêu-C. (Có một số hãy cẩn thận với điều này, nhưng bạn thực sự không muốn đến đó) Để biết thêm thông tin về ý nghĩa của việc vượt qua một cái gì đó bởi giá trị so với bằng tham chiếu, kiểm tra câu hỏi này: What's the difference between passing by reference vs. passing by value?
+0

Không chắc tôi hoàn toàn hiểu điều này ... nhưng cảm ơn cho lời giải thích anyway. – Pablo

+0

@Dave, không phải của tôi. Tuy nhiên, tôi không thể kết nối câu cuối cùng với phần còn lại của lời giải thích của bạn. "Cái đó" ám chỉ cái gì? Cũng không thể lấy phần bản sao. Từ những gì tôi có thể hiểu một cách đơn giản là nếu bạn có thể thay thế ngà bằng tự ngà, thì tự giữ lại, nếu không thì ngà sẽ được giữ lại. Nhưng cái gì là 'bởi giá trị',' bởi ref' vẫn không rõ ràng với tôi. Lấy làm tiếc. – Pablo

+0

@Michael câu trả lời cập nhật –

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