2010-08-27 34 views
14

Có một sự khác biệt giữa:Toán tử nào xóa?

operator delete(some_pointer); 

delete some_pointer; 

và nếu như vậy là những gì khác biệt và nơi người ta nên sử dụng một và nơi phiên bản khác của toán tử này? Cảm ơn.

+0

có thể trùng lặp của các toán tử [xóa và xóa \ [\] trong C++] (http://stackoverflow.com/questions/2425728/delete-vs-delete-operators-in-c) –

+0

liên quan http: // stackoverflow .com/questions/1913343/how-can-pairing-new-with-delete-có thể-dẫn-tới-bộ nhớ-chỉ rò rỉ –

+2

@ 0A0D: Câu hỏi này không liên quan gì đến việc xóa mảng. – UncleBens

Trả lời

22

Trớ trêu thay, toán tử deleteoperator delete() không giống nhau.

delete some_pointer; gọi trình phá hủy của đối tượng được trỏ đến bởi some_pointer và sau đó gọi tới số operator delete() để giải phóng bộ nhớ.

Bạn không thường gọi trực tiếp số operator delete(), bởi vì nếu bạn làm vậy, trình phá hủy của đối tượng sẽ không được gọi và bạn có thể sẽ bị rò rỉ bộ nhớ.

Lần duy nhất bạn phải quan tâm đến operator delete() là khi bạn muốn quản lý bộ nhớ của riêng mình bằng cách ghi đè operator new()operator delete().

Để đầu trang, bạn cũng nên biết rằng deletedelete [] là hai điều khác nhau.

+2

Đó chính xác là những gì tôi đang tìm kiếm. Cảm ơn. –

2

delete some_pointer; là "đúng" để sử dụng.

operator delete(some_Pointer); tồn tại chủ yếu như là một tạo phẩm của cú pháp để xác định bạn sở hữu toán tử xóa. Đó là, bởi vì bạn xác định một toán tử cộng như;

myclass::operator+(myclass b) {....} 

bạn thực sự có thể viết:

myclass c = a.operator+(b); 

nhưng không ai làm thế. Họ sử dụng:

myclass c = a + b; 

Tương tự, bạn có thể viết operator delete(some_Pointer); nhưng không ai làm được.

+2

Chúng thực sự không giống nhau ... – Dima

+0

@Dima: Tại thời điểm nào trong câu trả lời của tôi, tôi có nói chúng giống nhau không ?? Tôi chỉ nói để sử dụng "Xóa some_Pointer" và bạn có thể, nhưng không ai làm, sử dụng các hình thức khác. –

+3

Câu trả lời của bạn có vẻ không rõ ràng về điều đó ... –

6

operator delete() đơn giản giải phóng bộ nhớ. delete some_pointer gọi số some_pointer's destructor, và sau đó gọi operator delete().

2

Ít nhất trong kinh nghiệm của tôi, nó là phổ biến hơn để thực hiện operator newoperator delete hơn để thực sự sử dụng (ví dụ: cuộc gọi) cho họ, ít nhất là trực tiếp.

Thông thường, bạn sử dụng operator newoperator delete gián tiếp - bạn viết new expression, như A *a = new A;. Để thực hiện điều này, trình biên dịch tạo ra mã mà gọi operator new để cấp phát bộ nhớ liệu, sau đó gọi một A::A để chuyển đổi mà bộ nhớ thô thành một đối tượng A, nhiều càng tốt nếu bạn đã viết:

void *temp = operator new(sizeof A); // allocate raw memory with operator new 
A *a = new(temp) A;     // convert raw memory to object with placement new 

Khi bạn đã hoàn tất với đối tượng, bạn sử dụng delete A;.Để thực hiện điều đó, trình biên dịch sẽ gọi dtor cho đối tượng, và sau đó giải phóng bộ nhớ, khoảng như bạn muốn thực hiện:

a->~A(); 
operator delete(a); 

Ngoài ra còn có operator [] newoperator [] delete, được sử dụng khi/nếu bạn phân bổ/xóa mảng - nhưng không nhất thiết phải có bất kỳ sự khác biệt thực sự nào giữa phiên bản bình thường và phiên bản mảng - cả hai chỉ phân bổ một lượng bộ nhớ thô được chỉ định (mặc dù bạn có thể đoán rằng các phiên bản mảng sẽ phân bổ số lượng bộ nhớ tương đối lớn và thực hiện một số tối ưu hóa trên cơ sở đó).

Trong mọi trường hợp, nếu bạn muốn tối ưu hóa cách bộ nhớ được cấp phát cho các đối tượng của một lớp cụ thể, bạn quá tải để thực hiện điều đó. Có một số lượng hợp lý các triển khai hiện có mà bạn có thể thả vào và sử dụng, đặc biệt là cho các tình huống mà bạn dự kiến ​​phân bổ một số lượng lớn các đối tượng nhỏ để bạn cần giảm thiểu chi phí liên quan đến từng phân bổ (ví dụ: HeapLayers, khối nhỏ của Loki người cấp phát).

Một miếng ngon hấp dẫn chút: operator new, operator [] new, operator delete và operator [] xóa are always tĩnh class members, even if you don't explicitly include static` trong tuyên bố của họ/định nghĩa.

Ngoài ra còn có các phiên bản toàn cầu của cả bốn (::operator new, ::operator [] new, ::operator delete::operator [] delete). Những đánh dấu "biên giới" giữa quản lý bộ nhớ "nội bộ" C++, và thế giới bên ngoài. Thông thường, họ phân bổ bộ nhớ tương đối lớn từ hệ điều hành, và sau đó trả lại các phần nhỏ hơn cho phần còn lại của chương trình theo yêu cầu. Nếu bạn muốn (cố gắng) tối ưu hóa quản lý bộ nhớ cho toàn bộ chương trình của bạn, bạn thường làm điều đó bằng cách quá tải (hoặc, thực sự, thay thế) những điều này. Một lần nữa, lý do điển hình sẽ là nếu bạn mong muốn phân bổ rất nhiều đối tượng nhỏ (nhưng không chỉ trong một vài lớp). Một ví dụ về điều này là thư viện Boost Pool.

Việc sử dụng trực tiếp bất kỳ điều nào ở trên thường bị giới hạn trong các trường hợp bạn cần một khối bộ nhớ thô, không đối tượng. Một ví dụ sẽ triển khai các lớp chứa của riêng bạn. Ví dụ: std::vector thường sử dụng ::operator new (thông qua đối tượng Allocator) để cấp phát bộ nhớ để lưu trữ đối tượng. Vì nó cần có khả năng phân bổ dung lượng lưu trữ, nhưng chỉ sau (hoặc có thể không bao giờ) tạo đối tượng trong bộ nhớ đó, nó không thể chỉ sử dụng một cái gì đó như data = new T[size]; - nó phải cấp phát bộ nhớ thô, sau đó sử dụng vị trí mới để tạo đối tượng trong bộ nhớ khi bạn thêm chúng vào bộ sưu tập (ví dụ: khi bạn push_back một đối tượng). Điều này cũng đúng với std::deque. Nếu bạn muốn (ví dụ) để thực hiện bộ đệm tròn của riêng bạn "từ mặt đất lên", xử lý tất cả việc quản lý bộ nhớ trực tiếp thay vì sử dụng một cái gì đó như vector để lưu trữ, bạn có thể cần/muốn làm như vậy.

+0

cảm ơn câu trả lời tuyệt vời –