I have an object with a vector of pointers to other objects in it, something like this:
class Object {
...
vector<Object*> objlist;
...
};
Now, Objects will be added to list in both of these ways:
Object obj;
obj.objlist.push_back(new Object);
and
Object name;
Object* anon = &name;
obj.objlist.push_back(anon);
If a make a destructor that is simply
~Object {
for (int i = 0; i < objlist.size(); i++) {
delete objlist[i];
objlist[i] = NULL;
}
}
Will there be any adverse consequences in terms of when it tries to delete an object that was not created with new?
Yes, there will be adverse effects.
You must not delete an object that was not allocated with new. If the object was allocated on the stack, your compiler has already generated a call to its destructor at the end of its scope. This means you will call the destructor twice, with potentially very bad effects.
Besides calling the destructor twice, you will also attempt to deallocate a memory block that was never allocated. The new operator presumably puts the objects on the heap; delete expects to find the object in the same region the new operator puts them. However, your object that was not allocated with new lives on the stack. This will very probably crash your program (if it does not already crash after calling the destructor a second time).
You'll also get in deep trouble if your Object on the heap lives longer than your Object on the stack: you'll get a dangling reference to somewhere on the stack, and you'll get incorrect results/crash the next time you access it.
The general rule I see is that stuff that live on the stack can reference stuff that lives on the heap, but stuff on the heap should not reference stuff on the stack because of the very high chances that they'll outlive stack objects. And pointers to both should not be mixed together.
No, you can only delete what you newed
Object* anon = &name;
When name goes out of scope, you will have an invalid pointer in your vector.
What you're actually asking is whether it's safe to delete an object not allocated via new through the delete operator, and if so, why?
Unfortunately, this is obfuscated by some other problems in your code. As mentioned, when name goes out of scope, you're going to end up with an invalid pointer.
See zneak's answer for why your original question doesn't result in a safe operation, and why the scope for name actually matters.
This will not work - if you delete an object that wasn't allocated by new you've violated the rules or the delete operator.
If you need to have your vector store objects that may or may not need to be deleted, you'll need to keep track of that somehow. One option is to use a smart pointer that keeps track of whether the pointed to object is dynamic or not. For example, shared_ptr<> allows you to specify a deallocator object when constructing the shard_ptr<> and as the docs mention:
For example, a "no-op" deallocator is useful when returning a shared_ptr to a statically allocated object
However, you should still be careful when passing pointers to automatic variables - if the vector's lifetime is longer than the lifetime of the variable then it'll be refering to garbage at some point.
Related
I am not sure what exactly the command delete does in c++? As far as I know, to free memory I have to use delete on objects, that I previously instantiated with new, like:
Obj* object = new Obj();
delete object;
But does delete actually deletes data from my objects, does it in any way alter the object and data inside the object itself OR does it just call the corresponding destructor? If the destructor is empty, does useing delete have any consequences to the object? The reason for this question is as follows:
If I just delete objects this way, the pointer gets invalid, and my program does crash. So, I think I should just call the destructor with the delete command and take further steps inside the destructor function do actually do the cleanup and to be sure that other objects refering to this object know that the pointer is truly invalid.
Besides calling the destructor, the delete operator deallocates the memory that was previously allocated by new. This memory goes back to the available pool of memory that can be allocated.
This also means that object now points to invalid memory and any attempt to use it, or any other pointer that pointed to it, will invoke undefined behavior. This is probably what is happening in your program.
So your progam most likely has an issue with who "owns" the pointer. You shouldn't be calling delete on a pointer value that is still being used elsewhere in your program.
I have an object with a vector of pointers to other objects in it, something like this:
class Object {
...
vector<Object*> objlist;
...
};
Now, Objects will be added to list in both of these ways:
Object obj;
obj.objlist.push_back(new Object);
and
Object name;
Object* anon = &name;
obj.objlist.push_back(anon);
If a make a destructor that is simply
~Object {
for (int i = 0; i < objlist.size(); i++) {
delete objlist[i];
objlist[i] = NULL;
}
}
Will there be any adverse consequences in terms of when it tries to delete an object that was not created with new?
Yes, there will be adverse effects.
You must not delete an object that was not allocated with new. If the object was allocated on the stack, your compiler has already generated a call to its destructor at the end of its scope. This means you will call the destructor twice, with potentially very bad effects.
Besides calling the destructor twice, you will also attempt to deallocate a memory block that was never allocated. The new operator presumably puts the objects on the heap; delete expects to find the object in the same region the new operator puts them. However, your object that was not allocated with new lives on the stack. This will very probably crash your program (if it does not already crash after calling the destructor a second time).
You'll also get in deep trouble if your Object on the heap lives longer than your Object on the stack: you'll get a dangling reference to somewhere on the stack, and you'll get incorrect results/crash the next time you access it.
The general rule I see is that stuff that live on the stack can reference stuff that lives on the heap, but stuff on the heap should not reference stuff on the stack because of the very high chances that they'll outlive stack objects. And pointers to both should not be mixed together.
No, you can only delete what you newed
Object* anon = &name;
When name goes out of scope, you will have an invalid pointer in your vector.
What you're actually asking is whether it's safe to delete an object not allocated via new through the delete operator, and if so, why?
Unfortunately, this is obfuscated by some other problems in your code. As mentioned, when name goes out of scope, you're going to end up with an invalid pointer.
See zneak's answer for why your original question doesn't result in a safe operation, and why the scope for name actually matters.
This will not work - if you delete an object that wasn't allocated by new you've violated the rules or the delete operator.
If you need to have your vector store objects that may or may not need to be deleted, you'll need to keep track of that somehow. One option is to use a smart pointer that keeps track of whether the pointed to object is dynamic or not. For example, shared_ptr<> allows you to specify a deallocator object when constructing the shard_ptr<> and as the docs mention:
For example, a "no-op" deallocator is useful when returning a shared_ptr to a statically allocated object
However, you should still be careful when passing pointers to automatic variables - if the vector's lifetime is longer than the lifetime of the variable then it'll be refering to garbage at some point.
If I create an object without using the new keyword such as 'Object s(someval)', but that objects constructor uses new, when that object goes out of scope, will the destructor be called for it's new allocation? I feel as though it is, but I'm unsure.
Let’s give names to the objects, shall we?
struct A {
A() b(new B) {}
B* b;
C c;
};
A a;
Here, a’s destructor is called. So is A::c’s destructor (which is called automatically when a is destructed).
However, *A::b’s destructor is not called – actually, the pointer object A::b itself is properly released but since it’s a primitive type (it’s a pointer!) nothing happens. The pointee *A::b however needs to be manually destructed (and its memory released) by calling delete.
when that object goes out of scope, will the destructor be called for it's new allocation?
It depends on how Object is defined.
If the pointer returned by new is stored in some data member of Object on which delete gets called by the destructor of Object itself, then yes, the object allocated with new will be destroyed as well when s goes out of scope.
Otherwise, no. Every call to new must be matched by a corresponding call to delete before you lose the last pointer/reference to the allocated object, otherwise you will have a memory leak.
Since it is easy to fail to do so, and since it is also easy to dereference by mistake a pointer which is dangling (i.e. pointing to an object whose lifetime has ended), it is usually preferable to avoid performing manual memory management through raw pointers, new and delete (or their array counterparts).
When you need to control an object's lifetime, always prefer using RAII wrappers such as std::shared_ptr<> or std::unique_ptr<> unless you really know what you are doing and can't do otherwise.
No, you have to explicitly delete it in the destructor if you store that dynamically-allocated pointer as a data member. This also introduces the Rule of Three (Rule of Five in C++11), which is a bother. This is why stack-allocated objects should be preferred when possible.
When a pointer is necessary, make use of an RAII wrapper, such as std::vector for a dynamically-allocated array or a smart pointer, such as std::unique_ptr or std::shared_ptr, for a single dynamically-allocated object. These manage the memory for you and to you, it's no extra work.
No, it won't...
You have to define the delete in your destructor of the object you allocated using new.
You create an object on the heap using new and when your object is destroyed you will lose the reference to the object creating a memory-leak.
To avoid this, you might use a smart-pointer like shared_ptr.
No you will have to call delete explicitly for that object in the destructor
You cannot return an address of something that is defined locally so you must allocate memory on the 'heap' for this element to be placed so that other functions in the program may access it. Can someone explain this in more detail please.
MyClass* myFunc()
{
MyClass* pMC = new MyClass;
return pMC;
}
What is the purpose of the * in the function name? What is this indicating?
I realize that there is a creation of a pointer of type MyClass and it points to a new allocation on the 'heap' of this object. I just fail to understand what exactly the usefulness of this is.
What it means is that the object will always exist until it is explicitly destroyed.
Handling this destruction yourself is an immensely bad idea for a large number of reasons, and there exist a number of schemes that automatically clean it up at various points- unique or shared ownership, for example. This means that code which uses new directly is very bad, and triply so for new[], delete, or delete[].
In unique ownership, there is one pointer (std::unique_ptr<T>) which owns the object, and when it is destroyed, the object is destroyed. This is move-only. In shared ownership, when any (std::shared_ptr<T>) which points to the object is alive, the object remains alive. When the last one is destroyed, the object is also destroyed.
This is a very newbie question, but something completely new to me. In my code, and everywhere I have seen it before, new objects are created as such...
MyClass x = new MyClass(factory);
However, I just saw some example code that looks like this...
MyClass x(factory);
Does that do the same thing?
Not at all.
The first example uses dynamic memory allocation, i.e., you are allocating an instance of MyClass on the heap (as opposed to the stack). You would need to call delete on that pointer manually or you end up with a memory leak. Also, operator new returns a pointer, not the object itself, so your code would not compile. It needs to change to:
MyClass* x = new MyClass(factory);
The second example allocated an instance of MyClass on the stack. This is very useful for short lived objects as they will automatically be cleaned up when the leave the current scope (and it is fast; cleaning up the stack involves nothing more than incrementing or decrementing a pointer).
This is also how you would implement the Resource Acquisition is Initialization pattern, more commonly referred to as RAII. The destructor for your type would clean up any dynamically allocated memory, so when the stack allocated variable goes out of scope any dynamically allocated memory is cleaned up for you without the need for any outside calls to delete.
No. When you use new, you create objects off the heap that you must then delete later. In addition, you really need MyClass*. The other form creates an object on the stack that will be automatically destroyed at end of scope.