IMHO, theo cách nào là 'đúng' là vấn đề ưu tiên. Tôi không đồng ý với những người phản hồi, những người ủng hộ việc không sử dụng autorelease
, nhưng ưu tiên của tôi là sử dụng autorelease
trừ khi có lý do thuyết phục. Tôi sẽ liệt kê các lý do của tôi và bạn có thể quyết định có thích hợp với phong cách lập trình của bạn hay không.
Như Chuck đã chỉ ra, có một huyền thoại bán đô thị có một số loại phí sử dụng các bể tự động. Điều này không thể được tiếp tục từ sự thật, và điều này xuất phát từ vô số giờ sử dụng Shark.app để bóp phần cuối của hiệu suất ra khỏi mã. Cố gắng tối ưu hóa cho điều này là sâu vào lãnh thổ "tối ưu hóa sớm". Nếu, và chỉ khi, Shark.app cung cấp cho bạn dữ liệu cứng rằng điều này có thể là một vấn đề, bạn thậm chí nên xem xét tìm kiếm nó.
Như những người khác đã chỉ ra, một đối tượng được tự động phát hành được "phát hành tại một số điểm sau này". Điều này có nghĩa là họ linger xung quanh, chiếm bộ nhớ, cho đến khi "điểm sau" cuộn xung quanh. Đối với "hầu hết" trường hợp, đây là ở dưới cùng của một quá trình xử lý sự kiện trước khi vòng lặp chạy ngủ cho đến khi sự kiện tiếp theo (bộ đếm thời gian, người dùng nhấp vào một cái gì đó, vv).
Thỉnh thoảng, bạn sẽ cần phải loại bỏ những vật thể tạm thời đó sớm hơn là sau này. Ví dụ, bạn cần xử lý một tệp lớn, nhiều megabyte hoặc hàng chục nghìn hàng từ một cơ sở dữ liệu. Khi điều này xảy ra, bạn sẽ cần đặt một số NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
tại một điểm được chọn tốt, theo sau là [pool release];
ở dưới cùng. Điều này hầu như luôn luôn xảy ra trong một số loại "vòng lặp xử lý hàng loạt", vì vậy nó thường ở đầu và cuối của một số vòng lặp quan trọng. Một lần nữa, điều này nên được dựa trên bằng chứng, không dựa trên linh cảm. Object.It của Instrument.app là những gì bạn sử dụng để tìm những điểm rắc rối này.
Lý do chính tại sao tôi thích autorelease
để release
, tuy nhiên, là nó là nhiều dễ dàng hơn để viết các chương trình bị rò rỉ-miễn phí. Nói tóm lại, nếu bạn chọn để đi con đường release
, bạn cần phải đảm bảo rằng release
là cuối cùng gửi đến obj
, dưới tất cả hoàn cảnh. Trong khi điều này có vẻ như nó có thể là đơn giản, nó thực sự là đáng ngạc nhiên khó làm trong thực tế. Hãy ví dụ của bạn, ví dụ:
// array is an instance of NSMutableArray
MyClass *obj = [[MyClass alloc] init];
[array addObject:obj];
// Assume a few more lines of work....
[obj release];
Bây giờ tưởng tượng rằng đối với một số lý do, một cái gì đó, ở đâu đó, tinh tế vi phạm giả định của bạn mà array
là có thể thay đổi, có lẽ là kết quả của việc sử dụng một số phương pháp để xử lý các kết quả, và quay trở lại mảng chứa kết quả đã xử lý được tạo dưới dạng NSArray
.Khi bạn gửi addObject:
đến số NSArray
bất biến đó, một ngoại lệ sẽ bị ném và bạn sẽ không bao giờ gửi obj
thông báo release
của mình. Hoặc có thể họ gặp khó khăn ở đâu đó giữa khi obj
là alloc
d và cần cuộc gọi đến release
, như bạn kiểm tra một số điều kiện và ngay lập tức return()
do nhầm lẫn vì nó trượt tâm trí của bạn rằng cuộc gọi đến release
sau phải diễn ra.
Bạn vừa mới rò rỉ một đối tượng. Và có lẽ đã ký cho mình vài ngày cố gắng tìm ra nơi nào và tại sao nó lại bị rò rỉ nó. Từ kinh nghiệm, bạn sẽ dành nhiều giờ nhìn vào mã trên, tin rằng nó không thể là nguồn rò rỉ bởi vì bạn rất rõ ràng gửi obj
một release
. Sau đó, sau vài ngày, bạn sẽ kinh nghiệm những gì chỉ có thể được mô tả như là một biểu hiện tôn giáo khi bạn chứng ngộ nguyên nhân của vấn đề.
Hãy xem xét các trường hợp autorelease
:
// array is an instance of NSMutableArray
MyClass *obj = [[[MyClass alloc] init] autorelease];
[array addObject:obj];
// Assume a few more lines of work....
Bây giờ, nó không còn vấn đề gì xảy ra bởi vì nó hầu như không thể bị rò rỉ obj
vô tình, ngay cả dưới góc trường hợp cực kỳ bất thường hoặc đặc biệt.
Nếu bạn muốn mã của mình hoàn toàn an toàn, bạn nên sử dụng tự động phát hiện: Xem http://stackoverflow.com/questions/1147785/use-autorelease-before-adding-objects-to-a-collection/1149040#1149040 – Casebash