C++: Delete a struct?
I have a struct that contains pointers:
struct foo
{
char* f;
int* d;
wchar* m;
}
I have a vector of shared pointers to these structs:
vector<shared_ptr<foo>> vec;
vec
is allocated on the stack. When it passes out of scope at the end of the method, its destructor will be called. (Right?) That will in turn call the destructor of each element in the v开发者_高级运维ector. (Right?) Does calling delete foo
delete just the pointers such as foo.f
, or does it actually free the memory from the heap?
delete foo;
will delete the memory allocated to the foo structure, which includes the three pointers. But the memory pointed to by the pointers themselves will only be deleted if you implement a destructor that explicitly deletes them.
If you have dynamically allocated foo
, e.g.:
foo* f = new foo;
then delete f
will destroy the dynamically allocated foo
object including the pointers it contains but not anything pointed to by the pointers, if they do indeed point at dynamically allocated objects or arrays of objects.
If you've assigned a dynamically allocated foo
object (i.e. the result of new foo
) to a shared_ptr
(assuming tr1 or boost) then when the last shared_ptr
referring to that object goes out of scope delete
will be called on the pointer originally returned by new foo
automatically. You don't have to do this manually.
If your object (foo
) contains pointers to dynamically allocated objects that it owns (so need deallocating at the end of the lifetime of the foo
), then it's highly recommended that you write a destructor to deallocate these objects in the correct way (which will depend on how they are allocated).
Once you've written a destructor you need to consider whether you need to write a copy constructor and copy-assingment operator. As you are using a vector of shared pointers you may decide that your objects should not be copied. If so you can declare these as private and need not provide an implementation.
You should also consider one or more constructors to ensure that your pointer members are initialized. If the pointer members are never initialized then if they are not assigned to during the lifetime of a foo
then they will neither be null, nor point to a valid object and this is likely to cause an error in your destructor.
It only deletes the pointers.
You don't call delete f
where f is an object of type foo
if f
is stack allocated. You also don't call delete f
on a heap allocated object of type foo
if that address is stored in a shared pointer. shared_ptr
objets will call delete
for you when the last reference is freed.
Since your vector stores smart pointers they will also fall out of scope when your vector falls out of scope and the foo
destructor will be called and associated memory freed. The memory of foo
is only the size of 3 pointers though. Not what those pointers contain.
If the members of foo
are heap allocated, then you will need to delete
those separately. For example maybe within the foo destructor if the memory they point to is not shared between objects.
When it passes out of scope at the end of the method, its destructor will be called. (Right?)
Right.
That will in turn call the destructor of each element in the vector. (Right?)
Right. The destructor of the smart pointer.
or does it actually free the memory from the heap?
It calls the destructor of the smart pointer, if there are no more references to that pointer then the object it contains will be deleted and its memory will be freed.
There appears to be some terminological mixup in your question. Destructor of the vector will call destructors for shared_ptr
elements, which in turn will internally perform delete
on their stored pointers (if necessary).
Calling delete foo
, where foo
is a pointer to struct foo
, will call the destructor of struct foo
and then deallocate memory occupied by *foo
.
Destructor of the above struct foo
does absolutely nothing. It is trivial. If will not make any attempts to deallocate memory pointed by struct foo::f
or any other members. Why would it? It does not and cannot know whether that memory should be deallocated.
In fact, because struct foo::~foo
is trivial, the compilers will not normally even attempt to call it.
When it [vec] passes out of scope at the end of the method, its destructor will be called. (Right?)
Correct
That will in turn call the destructor of each element in the vector. (Right?)
Correct, this will delete the shared_ptr elements in the container, and if they are the last ones also the items they are sharing.
Does calling delete foo ...?
You cannot delete foo, it's a struct. You can delete an instance of foo.
Calling delete calls the destructor and frees the memory for the foo struct.
Does the foo destructor delete just the pointers such as foo::f, or does it actually free the memory from the heap?
That depends on the destructo, in this case you have a default destructor and so...
No, In the following example code you can see the some of the reasons why the default destructor associated with foo cannot cleanup any pointer referred items automatically.
{
char ca='a', *cb=new char;
int *i = (int*)malloc(sizeof(int));
foo a;
shared_ptr<foo> b = new foo();
a.f = &ca;
a.d = i;
b.f = cb;
}
精彩评论