Sign in to follow this  
__SKYe

[C++] Dynamic Memory Deallocation

Recommended Posts

__SKYe    1784
Hi there!

So, consider the following code:

struct ABC
{
int *myIntArray;
};

int *myVar;


myVar = new ABC[5];


myVar.ABC[0].myIntArray = new int[5];

My question is, if it's enough just to deallocate myVar (delete [] myVar), and the memory allocated in each myIntArray is deallocated too, or if i have to deallocate every single piece of allocated memory.

Sorry if it's confusing, but i think the point of the question is understandable.


Thanks in advance.

Share this post


Link to post
Share on other sites
Storyyeller    215
Yes, you have to delete any members that are dynamically allocated. You should really be using RAII and smart pointers though. Also, use container classes so that you don't have to worry about figuring out what sizes to delete in case of pointer decay.

Also, your code doesn't make sense.myVar is an int pointer so it can't have any members.


For example, if you instead do this, you won't have to worry about manual deallocation of the member data at all.
[code]
struct ABC
{
std::vector<int> myIntArray;
};

[/code]

Share this post


Link to post
Share on other sites
__SKYe    1784
Thank you for the reply.

About the code, sorry, complete mess, it's supposed to be something like this (for example):

struct VERTEX
{
float X, Y, Z;
};


struct MESH
{
unsigned int numVertices;
VERTEX *vertices;
};

struct MODEL
{
unsigned int numMesh;
MESH *meshes
};

And you'd do


MODEL myModel;
meshes = new MESH[numMesh];
meshes[0].vertices = new VERTEX[numVertices];


And that's about it (it's just an example)...

Hope it's more understandable. [img]http://public.gamedev.net/public/style_emoticons/default/smile.gif[/img]

Share this post


Link to post
Share on other sites
Storyyeller    215
I'd recommend doing something like this instead. It's much easier and less error prone.

[code]struct VERTEX
{
float X, Y, Z;
};

#include <vector>

struct MESH
{
std::vector<VERTEX> vertices;
};

struct MODEL
{
std::vector<MESH> meshes;
};


MODEL myModel;
myModel.meshes = std::vector<MESH>(numMesh);
myModel.meshes[0].vertices = std::vector<VERTEX>(numVertices);[/code]

Share this post


Link to post
Share on other sites
__SKYe    1784
Thank you, that is just awesome!

Sorry if it sounds weird, but it's just that i've heard about vectors before, and i always thought that it was the same as a normal array (char abc[10]), and so, it didn't fit my purpose of dynamicaly allocate memory at runtime.

Now after you show this, i went to read about vectors, and it's quite good.

However i have a question, i read that vectors use more space in memory than the one needed, in case of future reallocations, and that reallocation memory in a vector is costly in performance. But the thing is, in the above post example of a model loader, i only need to allocate memory once because it is only loaded once, and never changed again, and i've read that's possible to explicitly indicate a capacity by using vector::reserve, wich i think eliminates both problems (use extra memory, and performance cost).

But i'd like to hear your thoughts.

Thanks again...

Share this post


Link to post
Share on other sites
Aardvajk    13207
[source lang="cpp"]
struct Mesh
{
Mesh(unsigned count) : verts(count) { }
std::vector<Vertex> verts;
};

Mesh mesh(136);
[/source]

This will create the vector with 136 elements exactly. Provided you don't push_back() any additional vertices into the vector, no further allocations will take place, so this code is functionally equivalent to your original manual approach, but with all the additional safety that has been discussed.

Share this post


Link to post
Share on other sites
rip-off    10979
[quote]
However i have a question, i read that vectors use more space in memory than the one needed, in case of future reallocations, and that reallocation memory in a vector is costly in performance.
[/quote]
Vectors tend to allocate more space than they need when used with push_back() to avoid additional reallocations. But dynamic memory allocations be be expensive. It depends, if you are reading an unknown number of vertices from a file then vector's amortised push_back() will be reasonable, then you can use the "swap to size" trick:
[code]
vector<Foo> v;

// Fill v using push_back().

// Trim to size
vector<Foo>(v).swap(v);
[/code]
The latter is a little odd, but basically it creates a temporary copy of the vector (which will be the exact size required), and then swaps that into v. The over-allocated storage will be swapped into the temporary and deallocated at the end of the statement.

Share this post


Link to post
Share on other sites
__SKYe    1784
Well, you see i am using dynamic memory allocation (pointers), and even though i didn't know about vectors, it did the job perfectly (aside from some safety issues), because i don't need the push and pop functions of vectors.

When reading the vertices (for example), there's a line that has the exact number of vertices (somewhere in the file), so i only need to allocate memory once (the number of vertices won't change), so my problem was only that in vectors, even if i knew the exact number of vertices, the vector would allocate extra memory for future pushes or pops (in this case not needed).

Also, the performance issue of reallocation the vector isn't really a problem, due to, in this case, it would never be reallocated.

So the main problem was the extra unneeded memory.

Share this post


Link to post
Share on other sites
Storyyeller    215
You've got two options.

If the size is known at compile time, you can use boost::array. This is pretty much exactly like a static array except with the safety of a container class. The downside is that your class has to be templated with array size.

If the size isn't known at compile time, you'll have to use a resizeable container. But you can use encapsulation to prevent it from being resized after the initial creation.

[code]class Mesh
{
std::vector<Vertex> verts;

public:
Mesh(size_t i): verts(i) {}

Vertex& operator [](size_t i) {return verts.at(i);}
const Vertex& operator [](size_t i) const {return verts.at(i);}
size_type size() const {return verts.size();}
};[/code]

Share this post


Link to post
Share on other sites
rip-off    10979
[quote]
... my problem was only that in vectors, even if i knew the exact number of vertices, the vector would allocate extra memory for future pushes or pops
[/quote]
It only does this if you start pushing. If you use resize(), you can essentially control how often and how much memory is allocated.

The main benefit of using std::vector over raw pointers is that it will not leak. It won't leak if you return early from a function, it won't leak if an exception is thrown. Other advantages include checks during Debug builds that you aren't stepping outside the bounds of the vector.

If for whatever reason you're not going to use std::vector, I totally recommend that you at least write a small class to encapsulate the memory management. You can get both of the above advantages if you wrap the raw pointer in a small class.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this