Что происходит
Когда вы пишете T t;
, вы создаете объект типа T
с длительностью автоматического хранения . Он будет очищен автоматически, когда выйдет из области видимости.
Когда вы пишете new T()
, вы создаете объект типа T
с продолжительностью динамического хранения . Он не будет очищен автоматически.
Вам нужно передать указатель на него delete
, чтобы очистить его:
Однако ваш второй пример хуже: вы разыменовываете указатель и делаете копию объекта. Таким образом, вы теряете указатель на объект, созданный с помощью new
, поэтому вы никогда не сможете удалить его, даже если захотите!
Что делать
Вы должны предпочесть продолжительность автоматического хранения. Нужен новый объект, просто напишите:
A a; // a new object of type A
B b; // a new object of type B
Если вам нужна динамическая продолжительность хранения, сохраните указатель на выделенный объект в объекте автоматической продолжительности хранения, который автоматически удалит его.
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
Это распространенная идиома, которая называется не очень описательным именем RAII ( Resource Acquisition Is Initialization ). Когда вы приобретаете ресурс, который необходимо очистить, вы помещаете его в объект автоматического хранения, поэтому вам не нужно беспокоиться о его очистке. Это относится к любому ресурсу, будь то память, открытые файлы, сетевые подключения или что угодно.
Эта automatic_pointer
вещь уже существует в различных формах, я только что предоставил ее, чтобы привести пример. Очень похожий класс существует в стандартной библиотеке с именем std::unique_ptr
.
Существует также старый (до C ++ 11) с именем auto_ptr
, но теперь он устарел, потому что у него странное поведение копирования.
А потом есть еще более умные примеры, такие как std::shared_ptr
, которые позволяют использовать несколько указателей на один и тот же объект и очищают его только после уничтожения последнего указателя.