gì đang xảy ra
Khi bạn viết T t;
bạn đang tạo một đối tượng kiểu T
với thời gian lưu trữ tự động. Nó sẽ tự động được dọn sạch khi nó nằm ngoài phạm vi.
Khi bạn viết new T()
bạn đang tạo đối tượng thuộc loại T
với thời lượng lưu trữ động. Nó sẽ không được dọn dẹp tự động.
Bạn cần phải vượt qua một con trỏ đến nó để delete
để làm sạch nó lên:
Tuy nhiên, ví dụ thứ hai của bạn là tồi tệ hơn: bạn đang dereferencing con trỏ, và tạo một bản sao của đối tượng. Bằng cách này bạn sẽ mất con trỏ đến đối tượng được tạo ra với new
, vì vậy bạn không bao giờ có thể xóa nó ngay cả khi bạn muốn!
Bạn nên làm gì
Bạn nên thích thời gian lưu trữ tự động. Cần một đối tượng mới, chỉ cần viết:
A a; // a new object of type A
B b; // a new object of type B
Nếu bạn cần thời gian lưu trữ động, lưu con trỏ đến đối tượng được phân bổ trong đối tượng thời lượng lưu trữ tự động xóa đối tượng đó tự động.
template <typename T>
class automatic_pointer {
public:
automatic_pointer(T* pointer) : pointer(pointer) {}
// destructor: gets called upon cleanup
// in this case, we want to use delete
~automatic_pointer() { delete pointer; }
// emulate pointers!
// with this we can write *p
T& operator*() const { return *pointer; }
// and with this we can write p->f()
T* operator->() const { return pointer; }
private:
T* pointer;
// for this example, I'll just forbid copies
// a smarter class could deal with this some other way
automatic_pointer(automatic_pointer const&);
automatic_pointer& operator=(automatic_pointer const&);
};
automatic_pointer<A> a(new A()); // acts like a pointer, but deletes automatically
automatic_pointer<B> b(new B()); // acts like a pointer, but deletes automatically
Đây là một thành ngữ phổ biến mà đi bằng tên RAII không-rất-mô tả (Resource Acquisition là khởi). Khi bạn có được một tài nguyên cần dọn dẹp, bạn hãy gắn nó vào một đối tượng có thời lượng lưu trữ tự động để bạn không cần phải lo lắng về việc dọn dẹp nó. Điều này áp dụng cho bất kỳ tài nguyên nào, có thể là bộ nhớ, mở tệp, kết nối mạng hoặc bất kỳ thứ gì bạn ưa thích.
Điều này automatic_pointer
điều đã tồn tại ở nhiều dạng khác nhau, tôi vừa cung cấp nó để đưa ra ví dụ. Một lớp học rất giống nhau tồn tại trong thư viện chuẩn được gọi là std::unique_ptr
.
Cũng có một phiên bản cũ (trước C++ 11) có tên auto_ptr
nhưng hiện không được dùng vì nó có hành vi sao chép lạ.
Và sau đó có một số ví dụ thông minh hơn, chẳng hạn như std::shared_ptr
, cho phép nhiều con trỏ trỏ đến cùng một đối tượng và chỉ xóa nó khi con trỏ cuối cùng bị hủy.
Gần trùng lặp: [Thu gom rác tự động trong tiêu chuẩn C++?] (Http://stackoverflow.com/questions/1695042/is-garbage-collection-automatic-in-standard-c) – nobar