InitMyObject(MyObject* ptr)
{
*ptr = MyObject();
}
struct Data
{
MyObject obj;
};
extern Data data;
// ...
InitMyObject(&data.obj);
delete &data.obj; // ? is this ok
How I can delete (call deconstructor) data.obj, I also try Data::obj as pointer (nullptr default) then pass the pointer but crashed on Init.
How I can delete (call deconstructor) data.obj
The destructor of data will destroy its subobjects. Since data has static storage, it is automatically destroyed at the end of the program.
delete &data.obj; // ? is this ok
No. You may only delete the result of a non-placement new expression. You may not delete a pointer to a member object.
Related
class Example
{
private:
Example* pointer;
Example* pointer2;
public:
Example();
void setPointer2(Example* object);
};
Example::Example()
{
pointer = new Example();
}
void Example::setPointer2(Example* object)
{
this->pointer2 = object;
}
int main()
{
Example object;
object.setPointer2(new Example());
return 0;
}
Delete is not important. I just want to know what is the differences between this two object which is adresses holding by pointer and pointer2. Are they differently allocated? The actual question is, does it matter where to use the "new" operator?
A major problem you have in your code is infinite recursion! The constructor you have defined:
Example::Example()
{
pointer = new Example();
}
creates a new object of its own type. This will call the constructor (again), and that call will call the constructor (again and again...)
But, other than that issue, it doesn't really matter whether you create a new object by directly assigning its address to pointer or if you create the object elsewhere and then assign its address (later) to pointer2. Both will point to an object of the class.
`
class A{
public:
int x;
A* p;
};
int main(){
A obj1 = new A(); //no suitable constructor exists to convert from "A *" to "A"
A *obj2 = new A(); //Works fine
return 0;
}
`
Why is an object of class A declared as a pointer to that class, by default?
In other words, why does obj1 doesn't work but *obj2 does.
The new operator returns a pointer, so you can assign it only to a variable of pointer type.
You can use A obj1 = A();, which will simply call the constructor (without allocating dynamic memory, which is what new does) and return a A, not a A*.
No. Why is an object of class A declared as a pointer to that class, by default? Is incorrect. An object of class is just an object of that type and no pointer there.
The keyword new is used to allocate dynamic memory for a pointer. That is a memory must be cleaned up manually when you're done with it otherwise you will face a memory leak.
A* pObj = new A; // ok
A obj = new A; // error
A obj = *pObj; // ok:
Above obj is just an instance of class A and pObj is a pointer to an object of class A so inside the pointer there's the address of the object so to access it we dereference the pointer:
obj = *pObj = 0; // De-referencing pObj and assigning the value it points to to obj.
Finally clean up:
delete pObj; // ok
delete obj; // error
If an object exists as such:
MyClass obj;
To call a member function:
obj.myMemberFunction();
Then to call the destructor of that object after it fulfills its purpose:
delete obj;
However, lets say I have a pointer to an object:
MyClass* obj;
To call a member function:
obj->myMemberFunction();
Now... How do I call the destructor on this object?
You've got it backwards; do delete in the second case and not the first:
MyClass obj;
obj.myMemberFunction();
//delete obj;
//^^^^^^^^^^^
// NO! `obj` has automatic storage and will
// be destroyed automatically when it goes out
// of scope.
delete expects a pointer to a dynamically-allocated object:
MyClass* obj = new MyClass;
obj->myMemberFunction();
delete obj;
If you create it with
MyClass obj;
you do nothing to delete it. If you create it with
MyClass* obj = new MyClass();
you use
delete obj;
to delete it.
The operator delete is intended to be used with pointers that stores the adresses of areas allocated on the heap thanks to the corresponding operator new.
void function ()
{
int * pt;
pt = new int;
*pt = 42;
delete pt; // memory released
}
Memory allocated on the stack is automaticly released at the end of the corresponding scope :
void function ()
{
int i;
i = 42;
} // memory released
When you write MyClass obj;, the object is allocated on the stack, as opposed to on the heap. In this case, the object is destroyed automatically then it goes out of scope. The compiler generates code to ensure the destructor is called. So you don't delete the object explicitly.
delete is used when an object is allocated on the heap. For example:
MyClass* pobj = new MyClass;
// Do something with pobj...
delete pobj;
I have the following class:
class Stack {
struct Link {
void* data;
Link* next;
void initialize(void* dat, Link* nxt);
}* head;
public:
void initialize();
void push(void* dat);
void* peek();
void* pop();
void cleanup();
};
The pop method is:
void* Stack::pop() {
if(head == 0) return 0;
void* result = head->data;
Link* oldHead = head;
head = head->next;
delete oldHead;
return result;
}
oldHead is a pointer to a struct Link, which has a void pointer as member. So by deleting oldHead I'm implicitly deleting that void pointer, right?
I'm reading Thinking in C++ by Bruce Eckel, and it says that deleting void pointers doesn't clean things up properly because delete needs to know the type of the pointer.
This code is implicitly deleting the void pointer data, so: Can someone explain why is this (implicit) way of deleting a void pointer different from deleting with delete <void pointer>?
Your terminology is causing ambiguity, but let me explain. Let's say you have:
struct foo
{
void* bar;
};
Whenever a foo ends its lifetime, bar simply stops existing too. So if you have:
{
foo f = { new int; }
}
You've leaked, as new int is never deleted. Likewise, when you do:
{
foo* f = new foo;
f->bar = new int;
delete f;
}
You've still leaked, since when delete f is run, you simply end the lifetime of what f is pointing to (just like what happened automatically above), ergo bar simply ceases to exist and the new int is not deleted.
To summarize, when an object's lifetimes ends, delete is not called on the members that are a pointer.
So when you call delete on a Link, it's the same situation as bar in foo above: you're deleteing the memory for a Link causing data to stop existing, but not actually deleting what it's pointing at.
By deleting Link, that void* memory space is not being deleted. You need to define a destructor which deletes the memory that has been allocated. Each new needs one delete. An example of this for the Link-struct would be to add a destructor that deletes data. If your assumption would be correct, then next would also be deleted, causing your entire linked-list to be deleted which would be a terrible behavior.
Calling delete on a pointer will call the destructor of the pointed to type. If that type has no destructor, no such destructor will be called. This is the case for a void pointer which doesn't have a destructor. In the case of inheritance, the destructor should always be virtual so that the deepest class in the hierarchy will have their destructor called. The memory will be correctly free'd even if you cast your pointers to the wrong types - it's just that the destructor will be called incorrectly.
"I'm implicitly deleting that void pointer, right?"
Well, you're deleting the pointer itself when you delete oldHead. You're not deleting or freeing its target, which is what you seem to be wanting, and is what happens when you call delete on a pointer.
(To see why this is the case, consider that you might define a struct with a void* pointer that points to something outside the struct. You wouldn't want the target to be freed just because the struct was deleted.)
One problem with deleting a void pointer happens when you are pointing to something with a destructor:
#include <iostream>
struct foo
{
~foo() { std::cout << "important work" << std::endl; }
};
int main()
{
foo *f = new foo;
void *v = f;
delete v;
}
If you run the code sample above, you will see that the destructor is never called.
I've a situation like this:
class MyClass
{
private:
std::auto_ptr<MyOtherClass> obj;
public:
MyClass()
{
obj = auto_ptr<MyOtherClass>(new MyOtherClass());
}
void reassignMyOtherClass()
{
// ... do funny stuff
MyOtherClass new_other_class = new MyOtherClass();
// Here, I want to:
// 1) Delete the pointer object inside 'obj'
// 2) Re-assign the pointer object of 'obj' to 'new_other_class'
// so that 'obj' now manages 'new_other_class' instead of the
// object that just got deleted manually
}
};
Is there a way to achieve this? Will the following code do what I want?
void MyClass::reassignMyOtherClass()
{
// ... still, do more funny stuff (flashback humor :-)
MyOtherClass new_other_class = new MyOtherClass();
obj.reset(new_other_class);
}
Will the memory of new_other_class be de-allocated in the default destructor of MyClass?
Yes it will.
You can use
obj.reset( new MyOtherClass() );
And I'd better use such constructor
MyClass():
obj( new MyOtherClass() )
{
}
From MSDN where describing reset
The member function evaluates the expression delete myptr, but only if the stored pointer value myptr changes as a result of function call. It then replaces the stored pointer with ptr.
It will do what you want.