2009-03-20 32 views
6

Đây là một câu hỏi cấp độ mới bắt đầu, trong đó tôi tò mò nếu điều này là một sử dụng hợp lệ của một con trỏ trong một tuyên bố như:Đây có phải là cách sử dụng hợp lệ của con trỏ Objective-C không?

NSMutableDictionary *foo = [bar mutableCopy]; 

tôi bị lẫn lộn khi điều đó là hợp lệ so với khi tôi cần làm như sau:

NSMutableDictionary *foo = [[NSMutableDictionary alloc] initWithCapacity:0]; 
foo = [bar mutableCopy]; 
// use foo 
[foo release]; 

Cả hai đều hợp lệ? Khi nào sử dụng cái kia?

Trả lời

9

Đoán tại sao bạn có thể bị nhầm lẫn, tôi muốn thêm giải thích về mẫu mã thứ hai thực sự làm gì (và tại sao nó không cần thiết).

NSMutableDictionary *foo = [[NSMutableDictionary alloc] initWithCapacity:0]; 

Tôi nghĩ bạn đang bị nhầm lẫn bởi dòng này vì dòng này thường được mô tả là "khởi tạo foo". Đó là một chút sai lầm. Có 2 thực thể khác nhau về mặt kỹ thuật được thay đổi ở đây - đối tượng NSMutableDictionary mới được tạo và biến "foo" được gán địa chỉ của nó.

Dòng thực sự tạo đối tượng NSMutableDictionary mới trên vùng heap (vùng nhớ động của ứng dụng). Tôi sẽ gọi đây là "Từ điển 1". Vì vậy, đối tượng "Từ điển 1" mới này trên heap có thể được tìm thấy, địa chỉ bộ nhớ của nó được lưu trữ trong "foo". Vai trò của "foo" là hoạt động như một chỉ mục, vì vậy chúng tôi có thể tìm thấy "Từ điển 1".

Trong khi chúng ta thường nói: "foo là từ điển", đó là vì chúng ta lười biếng - tuyên bố về mặt kỹ thuật là sai. Chính xác: "có một từ điển trên heap và foo lưu trữ địa chỉ bộ nhớ của nó để chúng ta có thể tìm thấy nó và sử dụng nó".

Khi bạn sau đó chạy dòng:

foo = [bar mutableCopy]; 

bạn đang sử dụng địa chỉ trong "thanh" để tìm một đối tượng khác nhau (tôi sẽ gọi nó là "từ điển 2") trong heap, và làm chưa một đối tượng khác ("Từ điển 3") trên heap có cùng giá trị. Nếu bạn đang đếm, bây giờ là 3 đối tượng tồn tại.

Sau khi "Từ điển 3" được thực hiện, địa chỉ bộ nhớ của nó sau đó được lưu trữ trong biến "foo". Việc lưu trữ này vào "foo" sẽ ghi đè địa chỉ bộ nhớ hiện tại (địa chỉ được trỏ tới "Từ điển 1"). Điều này có nghĩa là chúng tôi không còn con trỏ đến "Từ điển 1" và do đó sẽ không bao giờ có thể tìm lại được nữa. Đây là lý do tại sao chúng tôi nói "Từ điển 1" đã bị rò rỉ.

Tôi hy vọng bạn có thể thấy từ tình huống này tại sao "Từ điển 1" không bao giờ cần thiết (bạn chỉ có ý định sử dụng "foo" để truy cập bản sao "Từ điển 3").

3

Điều đầu tiên là chính xác, bộ nhớ rò rỉ thứ hai vì bạn phân bổ hai lần (bản sao được tính là một) và chỉ phát hành một lần.

Đừng quên phát hành foo sau khi bạn đã hoàn tất mặc dù

+0

Không phát hành. mutableCopy trả về một đối tượng autoreleased. – NilObject

+0

từ tài liệu: Người invoker của phương thức, tuy nhiên, chịu trách nhiệm giải phóng đối tượng được trả về. – cobbal

+1

@NilObject: Không, không. Xem http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmObjectOwnership.html#//apple_ref/doc/uid/20000043-BEHDEDDB –

7

Bạn sẽ không bao giờ cần viết mã trong ví dụ thứ hai. [[NSMutableDictionary alloc] initWithCapacity:0] không làm gì ngoại trừ bộ nhớ bị rò rỉ.

Trong ví dụ thứ hai, bạn tạo NSMutableDictionary và gán nó cho foo. Sau đó, trong dòng tiếp theo, bạn gán một bản sao của NSMutableDictionary khác cho foo, có nghĩa là từ điển gốc foo được trỏ đến bây giờ chỉ trôi nổi ở đâu đó trên heap, không bao giờ có thể được giải phóng.

Bạn sẽ cần giải phóng foo trong cả hai trường hợp, tuy nhiên, như được trình bày trong số Objective-C memory management guidelines.

+0

Chỉnh sửa nhỏ: chuyển nhượng SAU dòng đó là thứ rò rỉ bộ nhớ. Tuy nhiên, tôi đồng ý với bạn rằng mã này sẽ không bao giờ được viết. :-) –

1

Tác vụ gán sẽ ghi đè giá trị trước đó được giữ bởi biến đó. Ví dụ:

x = 3 
x = 4 

Giá trị của x được tổ chức vào đầu dòng thứ hai là 3, nhưng sau khi dòng mã thực thi, nó là 4. Cú pháp:

int x = 0; 

thực sự chỉ là viết tắt cho điều này:

int x; 
x = 0; 

Các biến là con trỏ không khác nhau. Vì vậy, nếu tham chiếu đầu tiên của biến chỉ đơn giản là gán cho nó, bạn không cần phải khởi tạo nó lần đầu tiên, bởi vì bất kỳ giá trị nào bạn đang khởi tạo nó với chỉ đơn giản là sẽ bị loại bỏ.

0

Cách đầu tiên là đúng cách để thực hiện. Cả bản sao và phân bổ sẽ cấp phát bộ nhớ cho biến của bạn. Vì vậy, sử dụng tùy chọn thứ hai sẽ tăng số lượng lưu giữ của biến của bạn lên 2.

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