I learned C# first, and now I'm starting with C++. As I understand, operator new
in C++ is not similar to the one in C#.
Can you explain the reason of the memory leak in this sample code?
class A { ... };
struct B { ... };
A *object1 = new A();
B object2 = *(new B());
What is happening
When you write T t;
you're creating an object of type T
with automatic storage duration. It will get cleaned up automatically when it goes out of scope.
When you write new T()
you're creating an object of type T
with dynamic storage duration. It won't get cleaned up automatically.
You need to pass a pointer to it to delete
in order to clean it up:
However, your second example is worse: you're dereferencing the pointer, and making a copy of the object. This way you lose the pointer to the object created with new
, so you can never delete it even if you wanted!
What you should do
You should prefer automatic storage duration. Need a new object, just write:
A a; // a new object of type A
B b; // a new object of type B
If you do need dynamic storage duration, store the pointer to the allocated object in an automatic storage duration object that deletes it automatically.
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
This is a common idiom that goes by the not-very-descriptive name RAII (Resource Acquisition Is Initialization). When you acquire a resource that needs cleanup, you stick it in an object of automatic storage duration so you don't need to worry about cleaning it up. This applies to any resource, be it memory, open files, network connections, or whatever you fancy.
This automatic_pointer
thing already exists in various forms, I've just provided it to give an example. A very similar class exists in the standard library called std::unique_ptr
.
There's also an old one (pre-C++11) named auto_ptr
but it's now deprecated because it has a strange copying behaviour.
And then there are some even smarter examples, like std::shared_ptr
, that allows multiple pointers to the same object and only cleans it up when the last pointer is destroyed.