C++ Deleting a pointer to a object that contains another pointer - c++

Let's say
class A {
A* array;
public:
A (){
array= new A [4];
}
~A (){
delete array;
}
}
How do we free an object if we create such an object on heap like
A* object_ptr =new A();
I'm a bit confused about freeing a pointer that points to an object containing another pointer.....

Calling
delete object_ptr;
after
A* object_ptr =new A();
will invoke the destructor of the A pointed to by object_ptr. That means, if you fix your wrong
~A (){
delete array;
}
to
~A (){
delete[] array;
}
your code will be fine and the internal pointer is freed correctly.
However, you really should use std::vector instead of new[]. It will make your life a whole lot easier. If you insist on new[], read about The Rule of Three.

Two things to note.
When deleting arrays you should use []. For example: delete [] array;
When deleting pointers the destructor of the allocated object will get called. You would call from your code: delete object_ptr; to delete your pointer.
Another important point to be aware of is what happens when you copy your object. If your object ever gets copies you will have problems where one destructor deletes the pointers out from under another object. This is why shared_ptr is a good alternative to raw pointers (see this question on how to use shared_ptr).

Related

How do I destruct a dynamically allocated array of dynamic object?

I write a class vector whose member is a dynamically allocated array
template <typename T> struct vector{
T* elem;int capacity;
/*
*capacity is the size of array, not number of elements in the array .
*the default capacity is 3.
*/
vector(int c=3,T e=0){ /* initializing all elements as e */
T* elem=new T[capacity = c];
for(int i=0;i<capacity;i++){
elem[i]=e;
}
}
~vector(){
delete[] elem;
}
};
Now this is the point, regarding the destructor of vector. If the elements in the member elem is also dynamically allocated object obj, and this object also has its own destructor
int main(){
vector<obj*> vec;
vec.elem[0] = new obj(parameter)
vec.elem[1] = new obj(parameter)
vec.elem[2] = new obj(parameter)
...
}
Is it necessary to delete all the objects in the destructor of vector? like this
~vector(){
for(int i=0;i<capacity;i++){
delete elem[i];
}
delete[] elem;
}
Or I should only delete[] elem and the destructor of obj will finish the rest of work?
Is it necessary to delete all the objects in the destructor of vector? like this
Technically yes but what if you want a vector of pointers that does not represent ownership? You could easily end up either double-deleting an object, or trying to delete a stack-based object:
obj obj_a;
obj* obj_b = new obj;
vector<obj*> obj_ptrs;
obj_ptrs.elem[0] = &obj_a;
obj_ptrs.elem[1] = &obj_a;
obj_ptrs.elem[2] = obj_b;
delete obj_b;
Whether the pointed objects need to be deleted with the vector is none of the vector's business.
The cleanest way to address that is to use std::unique_ptr, which is an object type that holds a pointer and deletes it when it gets destroyed:
#include <memory>
template <typename T> struct vector {
// ...
~vector() {
// The vector is only responsible for deleting the array.
delete[] elem;
}
};
// ...
void foo() {
vector<std::unique_ptr<obj>> obj_ptrs;
obj_ptrs.elem[0] = std::make_unique<obj>();
obj_ptrs.elem[1] = std::make_unique<obj>();
obj_ptrs.elem[2] = std::make_unique<obj>();
obj stack_obj;
vector<obj*> obj_no_own_ptrs;
obj_no_own_ptrs.elem[0] = obj_ptrs.elem[0].get();
obj_no_own_ptrs.elem[1] = obj_ptrs.elem[0].get();
obj_no_own_ptrs.elem[2] = &stack_obj;
// Everything gets deleted
// No double-delete concern
}
In general, when you call delete in an object first it calls the destructor of the class, and second deallocate the memory where the object was allocated.
So, yes. If you create a class call vector it is necessary that you call delete if elem was dynamically allocated before with new.
New always have to be paired with delete. The standard approach was to, e.g. place the new in the constructor, and the delete in the destructor of a class.
In your case, in your class you are dynamically allocating space for other class, that happens to be also a dynamically allocated pointer.
first_object->second_object->third_object...
In this case first_object contain a dynamically allocated vector to second_object. second_object of course can contain more dynamically allocated memory.
In the destructor of your first_object, you delete the second_object so you call the destructor of the second object and deallocate its memory. The call to the destructor of the second_object should delete the third object, so its memory is also deallocated.
If you allocate memory and don't deallocate it, you start to mess the memory because you are fragmenting it. If you call delete without new, or in a object that has been already deleted there will be a segfault. It is always a good idea to place news in constructor and delete in destructors.
Nowadays you also can use shared_ptr or unique_ptr. They will automatically delete its content when they go out scope.
In particular shared_ptr will delete its content when the last pointer pointing to one resource goes out scope
unique_ptr will delete its content when it goes out of scope, since by definition forbid more than one pointer pointing to its content.
{
std::shared_ptr foo = std::make_shared();
std::shared_ptr foo2(new Foo());
}
Both shared pointers will delete its content automatically when they will go out of scope. The first option is preferred and more efficient (make_shared better than call the constructor with new). You could also use unique_ptr that are similar in characteristics to shared_ptr they don't allow more than one pointer pointing to the same resource.
I think you can read about smart pointers and about RAII and it will help you with this

delete operator with chained dynamic allocation

Let's assume I have two classes named classA and classB. I create a pointer to classA, and then dynamically allocate a single object using the new operator as follows:
classA *ptrA = new classA
classA has a member of type pointer to classB, and in its default constructor it allocates an array of objects of type classB on the heap as follows:
memberOfA = new classB[10]
and to complicate things further, classB has a member variable of type int*, and in its default constructor it allcoates an array of integer on the heap as follows:
memberOfB = new int[100]
Now, if I call a delete on ptrA using delete ptrA, how will the compiler go about deallocating the memory allocated by memberOfA and memberOfB.
Now, if I call a delete on ptrA using delete ptrA, how will the compiler go about deallocating the memory allocated by memberOfA and memberOfB.
When you call delete ptrA, the compiler will call the destructor of classA. If that destructor doesn't delete [] memberOfA then you're leaking both memberOfA and consequently memberOfB.
If instead of manual memory management (new and delete) you used automatic memory management (SBRM/RAII), then you wouldn't have to write any destructors and the resources you allocated would be freed as expected, for example:
std::unique_ptr<classA> ptrA(new classA);
std::unique_ptr<classB[]> memberOfA(new classB[10]);
std::unique_ptr<int[]> memberOfB(new int[100]);
This is in fact the modern C++ way to do it. The code becomes simpler to understand as the ownership semantics of the pointers are written in their type and there are no destructors lying around. An even better way would be to use std::make_unique(...) in place of new but I left it out for simplicity.
memberOfA and memberOfB is only deallocated if you put a delete[] in the destrutors of classA and classB. So if you had written the destructor of classA so that it freed the memory pointed to by memberOfA like this:
classA::~classA() {
delete [] memberOfA;
}
In this case the destructor would free the array calling the destructors of the elements pointed by the entries in memberOfA. The same can be said for the destructor of classB:
classB::~classB() {
delete [] memberOfB;
}
Remember using new must be paired with a subsequent delete at some point, if not you are look at a leak. Perhaps you should consider one of the smart pointer classes: unique_ptr, and shared_ptr.
If your design allows for classA and classB to use a unique_ptr or shared_ptr to the array, much of the dangers of a leak would have been overcome:
std::unique_ptr<classB[]> memberOfA(new classB[10]);
If the order of the deletion is of interest to you then, invoking the delete ptrA will result in the destructor of classA being called, and if we assume that it is implemented as hinted above (using delete []) then the delete [] operator will call the destructors of all the members in decreasing address order, quote from the Standard, draft N3690, ยง 5.3.5 / 6:
If the value of the operand of the delete-expression is not a null pointer value, the delete-expression will invoke the destructor (if any) for the object or the elements of the array being deleted. In the case of an array, the elements will be destroyed in order of decreasing address (that is, in reverse order of the completion of their constructor; see 12.6.2).
This will of course lead to the destructor of classB being called for each element, which will again utilize the delete [] memberOfB which will release the array pointing to the integers.
It will not ... you should do that by implementing the destructor! You can do that by using the delete [] operator.
classA::~classA() {
delete [] memberOfA;
}
and
classB::~classB() {
delete [] memberOfB;
}
and then you do delete ptrA the order of execution will be:
call classA::~classA()
call classB::~classB() on each of the elements of memberOfA
deallocate memory for the array of ints pointed by memberofB
deallocate memory for the array of memberofA
deallocate memory for classA
Deallocation of memory can actually happen at later stages in some cases.
Alternatively, if you don't really need to work with pointer use arrays or vectors to hold your elements.
class classB
{
...
std::array<int,100> memberOfB;
...
};
class classA
{
...
std::array<classB,10> memberOfA;
...
};
std::unique_ptr<A> ptrA(new classA)

Possible mem leak?

I'm new to the concept so don't be hard on me.
why doesn't this code produce a destructor call ?
The names of the classes are self-explanatory.
The SString will print a message in ~SString().
It only prints one destructor message.
int main(int argc, TCHAR* argv[])
{
smart_ptr<SString> smt(new SString("not lost"));
new smart_ptr<SString>(new SString("but lost"));
return 0;
}
Is this a memory leak?
The impl. for smart_ptr is from here
edited:
//copy ctor
smart_ptr(const smart_ptr<T>& ptrCopy)
{
m_AutoPtr = new T(ptrCopy.get());
}
//overloading = operator
smart_ptr<T>& operator=(smart_ptr<T>& ptrCopy)
{
if(m_AutoPtr)
delete m_AutoPtr;
m_AutoPtr = new T(*ptrCopy.get());
return *this;
}
By new smart_ptr<SString>(new SString("but lost")); you are creating a new, dynamically allocated smart pointer. You don't store the result of the allocation (a pointer to a shared_ptr to a SString) anywhere, it's dangling... since you don't store the result, you also can not call delete for it - therefore it's destructor won't be called, and in turn also the SString destructor of the contained object won't be called!
If you try
smart_ptr<SString> *p = new smart_ptr<SString>(new SString("but lost"));
delete p;
instead, you will see the destructor called also for this case.
However, that's no sensible use of a smart_ptr. smart_ptr were created so that you don't need to call delete manually; therefore, don't use them that way; use them as in your first statement!
The point of a smart pointer is that you're supposed to have only automatic smart pointer objects:
{
smart_ptr<Foo> p(new Foo);
}
// bye bye Foo
Your second line, however, creates a dynamic smart pointer, whose life never ends! Thus it never gets a chance to destroy the object it's in charge of.
You would have to delete the smart pointer itself manually, so that it can in turn clean up the object:
auto sp = new smart_ptr<Foo>(new Foo);
// ^^^^^^^
// ^^^^^^^^^^^^^^ +------< dynamic Foo, handled by the SP
// |
// +---------------< dynamic smart pointer, handled by YOU
delete sp;
Yes, the smart point itself is leaked. (And anything it holds a reference to).
I cannot think of a good reason to new a smart pointer...
Yes, it is a memory leak, you're leaking the second smart pointer and its contents.
The reason is that the first smart pointer is created on the stack, so its life-time is scoped to the block it is declared in, after that it will be automatically destroyed.
The second one is created on the heap, which means it will live until you destroy it with delete at which point its destructor will be called (and with that the destructor of the SString it is holding).

c++ must delete a references?

in the following code:
class x
{
private:
someRef& m_ref;
public:
x(someRef& someRef):m_ref(someRef)
{
}
do I need to do:
~x()
{
delete m_ref;
}
which by the way doesnt work without getting the pointer...
basically I'm asking: Do I need to call a destructor on a reference member?
No.
You only need to delete an object if you own it. If you were passed a reference, it means that someone else owns it, thus it's unnecessary and thankfully the language prevents it.
I don't think one actually strictly speaking ever deletes even pointers. What you delete are dynamically allocated objects (or arrays of objects) that the pointer is a handle for. If the object originates from a call to new and it is the responsibility of this class to clean up after this object, then you call delete.
It is technically possible that a reference might be referring to a dynamically allocated object:
int main()
{
//in principle a reference can also refer to a dynamically allocated object
x var(*new someRef);
}
//and if that is the intended usage:
x::~x()
{
delete &m_ref;
}
However, this would be incredibly bad style. By convention, the "owning" handle of a dynamically allocated object should not be a reference.
No. You can only delete pointers, not references, and even then you must only delete objects that you allocated using the new operator. And then you must be sure to delete them only once. Here is the case in which you would need to use delete in your destructor:
class x
{
private:
someObj* m_ptr;
public:
x():m_ptr(new someObj())
{
}
~x()
{
delete m_ptr;
}
But in general it's best to avoid even this and use smart pointers instead.
I want to clarify some misconceptions you seem to have that are beyond the intent of your question:
When a class's destructor is called all of it's members' destructors get called as well.
Calling delete is not the same as calling the destructor. delete explicitly calls the destructor and also calls operator delete at the objects location, it is a 2 part thing.
For a small bit of extra clarification I want to offer the following:
int *pi = new int;
//int& ir = pi; // can't do
// this a reference to the pointer but it is an error
// because or the type difference int& vs int* and
// static_cast won't help. reinterpret_cast would allow
// the assignment to take place but not help the 'delete ir'
int& ir = *pi; // this is OK - a reference to what the pointer points to.
// In other words, the the address of the int on the heap.
//delete ir; // can't do, it is a reference and you can't delete non-pointers.
delete &ir; // this works but it is still not "deleting a reference".
// The reference 'ir' is another name for the heap-based int.
// So, &ir is the address of that int, essentially a pointer.
// It is a pointer that is being used by delete, not a reference.

Exception Handling Code Please explain it

Please see the following code and its output - please explain me the code
void abc(int);
class A
{
public:
A()
{
cout<<"Constructor Called";
}
~A()
{
cout<<"Destructor called";
}
};
int main()
{
try
{
abc(-1);
}
catch(int p)
{
cout<<p<<endl;
}
return 0;
}
void abc(int p)
{
A * Aptr = new A[2];
if(p<0)
throw p;
}
Output:
Constructor Called
Constructor Called
-1
can anyone explain why is the destructor not being called as in the case of normal stack unwinding
This pointer:
A * Aptr = new A[2];
is a raw pointer. When it goes out of scope only the pointer itself is destroyed - nothing is done to the array it points to. So the array is not delete[]'ed and the destructors are not called. It's a typical example of a memory leak.
There're three typical solutions to the problem:
allocate the array itself on stack
use std::vector
use a smart pointer (not std::auto_ptr - it is not suitable for using with arrays.
The destructor is not called because the objects you allocate are never deleted. You would get the same output if you removed the throw.
If, on the other hand, you changed your function into this:
void abc(int p)
{
A A_array[2];
if (p<0)
throw p;
}
You would see that the destructor was called.
As mentioned elsewhere, C++ pointers do NOT delete the memory they point to when going out of scope. You have a few options:
The hard way - try and do the memory management yourself. This way lies memory leaks and buffer overflows. Try not to do this.
void abc(int p)
{
A * Aptr = new A[2];
if(p<0)
{
delete [] Aptr;
throw p;
}
delete [] Aptr;
}
Put the array on the stack and let the normal stack unwinding handle it:
void abc(int p)
{
A Aptr[2];
if (p<0)
throw p;
}
Instead of using a raw pointer to point to the newly allocated array, hold onto it using a smart pointer class like scoped_array or shared_array, or some other RAII class:
void abc(int p)
{
boost::scoped_array<A> Aptr (new A[2]);
if(p<0)
throw p;
}
}
2 and 3 are really the only safe options in C++ code that uses exceptions - if you use raw pointers and manual memory management, you WILL end up with memory leaks sooner or later. No matter how careful you are, exception safe code pretty much requires RAII.
In addition to the suggestions concerning boost::shared_array and boost::scoped_array you could also just use std::vector:
std::vector<A> array( 2 );
if( p < 0 )
throw p;
Note that your types should be copyable if you go this route, however, as std::vector will copy them around during insert or when internally resizing, et cetera.
Could it be because you are not calling delete on your A class? If you don't delete a dynamically allocated class the desnstructor is not called.
because you allocated on the heap. What gets freed are the variables holding the pointer to the array of objects. Not the objects themselves.
Aptr is a heap-allocated variable, not a stack variable. You need to explicitly delete it for the destructor to be called (and to free the memory).
If you would instead do this:
A a[2];
and not
A *Aptr = new A[2];
you'd get the destructor called.
Anything you allocate dynamically you will have to deallocate yourself.
You created the object on the heap. The destructor will be callen when you delete the object.
If you don't create the object on the heap, the destructor will be called as you expected.