I have an array of pointers: pArray[rows][columns], where each element can contain a pointer to an object. Some of the objects were instantiated in main() on the heap, and some were instantiated by objects themselves also on the heap: That is, I passed pArray to an object member function, and that function created a new object, and put a pointer to it in pArray.
Now when I want to delete pointers to objects from pArray, is there ownership in play here? Meaning, if an object created a new object and placed a pointer to it in pArray, can only the creator object call delete on that pointer? Or can I do it from main(), and other objects by passing the array to them?
Some more details:
The code simulates a predator prey model on a grid (pArray). So I begin by reading in the initial grid config from a file, and instantiate objects (predators, and prey), on pArray from main(). But predators and prey can breed, so objects spawn new objects and by passing pArray to them, they instantiate their children on pArray.
With raw pointers ownership is purely a concept. As long as you are working with raw pointers, it is entirely up to you to assign ownership of pointed object to anyone and anything. It is a matter of your design. There's no such "rule" that the object should be deleted by whoever created them. Ownership can be retained or passed on. Ownership can be shared (as in reference-counted ownership schemes). Again, it is a matter of your design and your intent.
Various smart pointer classes will help you to express your intent and implement your intent. With raw pointers you have to remember who owns what and do everything manually.
No, there is no "ownership" on pointers in C++, if the pointer is valid (contains proper reference to data / object), you can deallocate it anywhere issuing delete command.
The destructor of objects is subject to the same public/protected/private like every other method. So, if the destructor is public, anyone can call delete on the object.
The only important thing is that it happens exactly once, and only after nobody is using the object anymore.
There is no ownership concept for pointers in C++ .As far as I understood your question, Yes you can delete that object from main() in case of dynamic memory allocation. The memory allocated to that object would only be freed only when the program ends or the Object array goes out of scope and the destructor for the class is called.
Related
In my method a Player object is created like:
Player player(fullName,age);
My teacher gave us a piece of code with a constructor that takes a shared_ptr to a player object.
//constructor of the class
SomeClass(const std::shared_ptr<Socket> client, std::shared_ptr<Player> player)
Lets say we want to call the constructor of SomeClass and pass the player object we created on stack.
Is it ever safe/possible/good to create a shared_ptr from a stack object?
To make the question more understandable lets say we have two big code projects and we want to merge them so a method from one project is called from another one, should we rewrite all the files to use shared_ptr or stack objects exclusivly (for the methods that needs to be connected) or should we just create a shared_ptr to the stack object.
Why im not sure of the result:
What if the scope where the stackobject is created ends but the shared_ptr is still used and vise versa.
The stackobject gets deleted when out of scope or does it stay alive because there is still a reference to the object (in another class though)?
The shared_ptr goes out of scope and tries to delete the object, can it even though the stackobject is refering to it?
Note: I know I could just use the following and pass player
shared_ptr<Player> player{ new Player {fullName,age} };
Is it ever safe/possible/good to create a smart_ptr from a stack object?
Safe? Only if you can guarantee that the stack which created that object will only be ended after all shared_ptr's that pseudo-own it.
Possible? Sure: pass shared_ptr's constructor a deleter object that does nothing:
auto sptr = shared_ptr<Player>(&player, [](Player *) {});
When the last shared_ptr is destroyed, the deleter will be called and nothing will be deleted.
Good? Not really. As noted above, safety is not something that can be universally guaranteed in such code. Depending on your code structure, this may be legitimate. But it requires great care.
This SomeClass is expecting to claim ownership of a resource; that's why it's taking a shared_ptr. You're kind of lying to it by passing it a shared_ptr that doesn't really own the object it references. That means the onus is on you and your code structure to not violate the promise you made to SomeClass that it would have shared control over that object's lifetime.
The purpose of a shared pointer is to manage the lifetimes of dynamically created objects. As long as there is any shared pointer that points at an object, that object must still exist; when the last shared pointer that points at an object is destroyed, that object gets destroyed.
Stack objects have a fundamentally different lifetime: they exist until the code exits from the scope in which they were created, and then they are destroyed.
The two notions of lifetime are incompatible: there is no way a shared pointer can ensure that a stack object that has gone out of scope still exists.
So don't mix the two.
Is it ever safe/possible/good to create a shared_ptr from a stack object?
I agree with #Nicolas Bolas that it is not safe. But it may be safe to create a shared_ptr from a copy of a stack object
shared_ptr<Player> playerPtr(new Player(player));
if Player is copy-able of course.
It's not safe to create a shared pointer to a stack object, because the stack object is due for destruction as soon as its containing function returns. Local objects are allocated and deallocated implicitly and automatically and trying to intervene is surely invoking many kinds of undefined behavior.
Use move semantics to create the shared_ptr
std::shared_ptr<Player> player_shared_ptr{ std::make_shared(std::move(player)) };
In this way, a copy is avoided. You may need to implement move constructor though on relevant classes for this approach to work. Most/all std objects support move semantics out of the box (eg. string, vector, etc.)
Safe is a strong word.
However, You can make the code safer by defining a StackObjectSharedPtr, forcing the shared_ptr instanciated type to include a "special" StackObjectDeleter
using PlayerStackSP = std::shared_ptr <Player, StackObjectDeleter> ;
class StackObjectDeleter {
public:
void operator () (void*) const {}
};
Player player(fullName,age);
std::shared_ptr<PlayerStackSP, StackObjectDeleter> player(&player, StackObjectDeleter());
The StackObjectDeleter replaces the default_delete as the deleter object. default_delete simply calls delete (or delete []). In case of StackObjectDeleter, nothing will happen.
This is a step further of #Nicol Bolas's answer.
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
Will the smart pointer or scoped pointers delete an object when the class has no destructor
If not, why not just leave the scope and let the object be deleted by itself?
All class members are deleted even if you don't have a destructor when the instance is deleted. Memory leaks occur when you deal with pointers:
class A
{
private:
B* b;
};
In this case, b itself will be destroyed when the instance of A is deleted, but the memory it points to will not.
class A
{
private:
SmartPtr<B> b;
};
In the case of smart pointers, which usually have some reference counting and memory cleanup in the destructor, the memory it points to will be explicitly destroyed by its destructor, and the destructor of the smart pointer will be implicitly called when the instance of the containing class is destroyed.
yes. that s what smart pointers are used for.
http://www.boost.org/doc/libs/1_48_0/libs/smart_ptr/smart_ptr.htm
http://en.wikipedia.org/wiki/Smart_pointer
What is a smart pointer and when should I use one?
Yes, smart pointer deletes the object irrespective of whether class has destructor or not. Note that smart pointers are used with objects allocated on heap (using new) and these object won't release memory when they go out of scope, you need to explicitly delete them. Smart pointers will remove this process of explicitly deleting them.
The pointer to the object itself will be deleted. However if there is any dynamically allocated data in the class it will not get freed. The idea of having a destructor is to be able to post-process the class object and mainly - free any resources taken.
new and delete do two things.
new allocates memory and gets an object to construct itself in that memory space.
delete first gets the object to destruct itself then releases the memory.
Note that some smart pointers can be given a custom deleter which doesn't call delete on the object but whatever you ask it to do. There may be occasions when you wish to pass it a no-op.
Your point is well taken; there aren't that many uses for smart pointers
in C++, since most of the time where they might be relevant, you'd be
better off using value semantics, and copying. In the case of
scoped_ptr, the most frequent use is when the actual object is
polymorphic:
scoped_ptr<Base> pObj = condition
? static_cast<Base*>( new Derived1 )
: static_cast<Base*>( new Derived2 );
(Regretfully, at least one of the static_cast is necessary.)
If you are dealing with a container of polymorphic objects, you'll need
shared_ptr instead, and if you're returning a polymorphic object, or
otherwise passing it around, you will use unique_ptr if you can
guarantee its availability, and auto_ptr otherwise—in some cases
where you're passing it around, shared_ptr might be more appropriate.
In the case of returning an object or passing it around, the cost of
copying it might also be a motive for using a smart pointer, even if the
object isn't polymorphic. In such cases, I'd still use value semantics
(i.e. copying and assigning the object itself) unless I had a
performance problem.
Note that smart pointers aren't only used for memory management. I
regularly use auto_ptr in the interface of queues between threads:
once the object has been inserted into the queue, it no longer belongs
to the sending thread; auto_ptr expresses these semantics exactly,
with the auto_ptr in the sending thread becoming invalid. Or a
modifiable singleton (something which should be very, very rare) might
acquire a lock in its instance function, and return a shared_ptr
which frees the lock in its final destructor. I've also used smart
pointers in one or two cases to ensure transactional semantics: in one
case, for example, the objects were in a number of different sets (which
held pointers to them, of course), ordered according to different
criteria. To modify an object, you acquired a shared pointer to it; the
function which returned this shared pointer also removed the objects
from the sets, so that you could safely modify the key values as well,
and the final destructor reinserted them into the sets according to the
new keys. And so on—there are any number of uses for smart
pointers that have nothing to do with memory management or object
lifetime.
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.
Sorry if my last question is very similar, but I have another query of when and if I should use the delete keyword.
Example code.
I initialize a class that has pointer to vector of pointers as their arguments. These objects are assigned memory from the heap. I then pass these objects to my class constructor which is also assigned memory from the heap.
Here is the code:
in the main function
//This will also change each loop
vector<A*>* ex1 = new vector<A*>;
vector<B*>* ex2 = new vector<B*>;
vector<C*>* ex3 = new vector<B*>;
for(int i =0; i < 10; i++){
ex1->push_back( new A(i); );
ex2->push_back( new B(i); );
ex3->push_back( new C(i); );
}
MainClass* ex_main = new MainClass(ex1,ex2,ex3);
inside MainClass.cxx
MainClass::MainClass(vector<A*>* ex_A, vector<B*>* ex_B, vector<C*>* ex_C): m_ex_A(ex_A), m_ex_B(ex_B), m_ex_C(ex_C) {}
inside MainClass.h
vector<A*>* m_ex_A;
vector<B*>* m_ex_B;
vector<C*>* m_ex_C;
m_ex1, m_ex2 and m_ex3 have been assigned to the stack, but have been assigned to the pointer to vector of pointers.
Questions.
Do I delete the m_ex_A,B ans C in the destructor of class MainClass (I know I will need to delete the elements in each vector as well) and also the pointer to vector of pointers in the main function?
e.x. in destructor of MainClass (I do something a bit more generic than this, but this is quicker to show )
for(int i = 0; i < m_ex_A->size(); i++){
delete m_ex_A->at(i);
}
delete m_ex_A;
I would then do a similar approach for pointer to vector of pointers ex1, ex2, ex3 in the main function and also delete the main class.
My confusion comes from the fact that m_ex_A,B and C are assigned to the Stack and not dynamically, but they get assigned to dynamic objects?
My guess would be to use delete to m_ex_A,B, C objects as I have dynamically initialized them?
Also what is more efficient using heap memory or stack??
I think I might be using dynamic memory to much...
You definitely should delete your dynamically allocated objects somewhere. Could as well do it it the destructor of MainClass, but personally, I'd consider it a bad style. Why? Because you're allocating and deleting in different places, in different entities. In fact, you're transferring ownership of these objects, so you should be very careful to not to delete twice or something. I'd rather use shared_ptr or unique_ptr and releave my mind of all this micromanagement. You can search those on the web, and they are extremely easy to use.
As for the second question - you MUST only delete every object once. Copying pointers doesn't create new object, it's just another pointer to the same object.
This is not a direct Answer to the question but trying to clear up the underlying issue:
The conceptual issue is that raw pointers do not convey (and worse have no way of) ownership information. They are just a pointer to a memory location.
Now, whenever you allocate dynamic memory with new you are responsible to delete it somewhere.
To decide where this somewhere is is part of designing your program. If you pass a pointer to some object like in your example you need to document if the object takes ownership of the passed in pointed to memory (in this case the object becomes responsible for cleanup) or if it does not (and the caller remains responsible).
With raw pointers there is no way of knowing (except for documentation or examining the implementation) whether or not any given function takes ownership.
This is where the new C++11 (also available from boost) smart pointers (unique_ptr and shared_ptr) fit in. They immediately convey who is responsible for deleting the memory and even better take care of doing so automatically (and with little- or in case of unique_ptr no- overhead)
So as a final guideline: Never ever use raw pointers instead of smart pointers or some other kind of RAII mechanism! (until you gain much more experience with those and can prove that raw pointers are in fact a better solution in that special case)