Hey folks, just a quick question i can't seem to find the answer to. If i overwrite a container with a pointer in it, does the pointer and therefore the object it points to still exist, and would that be considered a bad handling of memory.

For instance. I have 2 vectors pointers to objects:

vector<DNA*>			m_vPopulation2;
vector<DNA*>			m_vParentPop2;

I know they are the same size, although would that matter?. And i want to make m_vPopulation2 = m_vParentPop2. Basicly i want all the elements inside population to become the elements inside ParentPop. Could i just write:

m_vPopulation2 = m_vParentPop2;

or would i have to loop through and transfer each pointer and then delete the origonal? Like this:

for(int i=0; i<m_vPopulation2.size(); i++)
{
	delete m_vPopulation2[i];
	m_vPopulation2[i] = m_vParentPop2[i];
	delete m_vParentPop2[i];
}

or something similar?

Alternativly if there is a better way to do this and im being a tard please let me know.

Thx!

Recommended Answers

All 8 Replies

I'm assuming the pointers point to dynamically allocated data, probably allocated with "new" ?

In that case, it is very important you do not lose track of the pointers that point to data allocated with "new". When you copy a pointer to the vector that has pointers in it, if you're over-writing a pointer pointing to data you may lose the only pointer to the location of the data in memory, and thus will leak memory.

It is my opinion that the proper way to do it is actually to use a smart pointer type, such as those provided by the boost lib. See boost::shared_ptr<>

Otherwise, if you must use raw pointers, delete the pointer you are going to over-write, set it to nullptr, then copy the new pointer over. If you wish the pointer to still be useful, do NOT call delete on the other copy of hte pointer in the other vector.

Instead, set it to nullptr.

Ex:

for(int i=0; i<m_vPopulation2.size(); i++)
{
	delete m_vPopulation2[i];
	m_vPopulation2[i] = m_vParentPop2[i];
        m_vParentPop2[i] = nullptr;//or NULL (0x0)
}

Since they are raw pointers you would have to deallocate each pointer manually. If you want to use something like m_vPopulation2 = m_vParentPop2 then you should instead use smart pointers instead of raw pointers.

If both of the vectors are the same size then you can do this :

for(int i = 0; m_vParentPop2.size(); ++i){
  DNA* elem = m_vPopulation2[i];
  m_vPopulation2[i] = new DNA(*(m_vParentPop2[i]); //make a copy of DNA
  delete elem; //delete the old element
}

When you copy the vectors of pointers you copy the locations they hold, meaning, you copy the address of the vector you're copying. The pointers then no longer have access to their previous values and if you initialized those values with the pointers they are now lost and cannot be accessed.

Because your vectors deal with pointers, they can only pass pointers, you can't pass values. There is a few methods to remedy this. We can create a new array to hold non-pointers of the same type, which we will call the "buffer". You need to copy the contents using an iterator of the first vector into the buffer, then copy the contents of the buffer into the second vector.

Remember, because you're grabbing the the reference of a pointer with a pointer, you need to use:

** iPointer

when grabbing the values.

Show me what you get.

thx for the help so far guys! but there are some differences in the way i am doing things compared to what you are presuming im doing. Appologies i should have put in more context.

i dont actually use the 'new' command anywhere. A typical contructor call and addition to the vector looks like this:

DNA testDNA2(126, m_iChromeLength, m_fMutateChance, m_iCrossoverChance, m_RanGen);
m_vPopulation2.push_back(&testDNA2);

I had thought this was acceptable, a pointer being just a storage for an address of the thing it points to after all. Is this wrong? or somwhow inefficient? Should i be doing this instead:

m_vPopulation2.push_back(new DNA(126, m_iChromeLength, m_fMutateChance, m_iCrossoverChance, m_RanGen));

or even something else? Well regardless of that i have stumbled apon a related problem. In the loop that is trying to transfer the data from 1 vector to another i tried what psudorandom21 said:

delete m_vPopulation2[i];
m_vPopulation2[i] = m_vParentPop2[i];
m_vParentPop2[i] = NULL;

However i had a rather odd error, or lack of an error. All that happened when i ran this was it compiled fine then as soon as it reached the delete command it just stopped and windows made an error sound. No message though, no compiler warnings or anything like that. I even f-11'ed through the process and it just stops at the delete. Now i think, although not totaly sure, that its because i have no 'new' clause and u can only 'delete' pointers that have been created with 'new'. But i do have a reason to doubt that, and thats in the destructor of the DNA class itself. Which has a member variable and destructor of:

unsigned int*		m_iGenes; //within .h file
//...
m_iGenes = new unsigned int[m_iChromeLength]; //within constructor
//...
DNA::~DNA() //destructor
{
	delete m_iGenes;
      //delete [] m_iGenes;
}

and the destructor here throws the same error or lack thereof.

On a side note, im now looking into smart pointers. Hadnt heard of them before so will try to learn what i can about them and implement them acordingly. Thanks for the pointer (get it? no?.. nvm)

(get it? no?.. nvm)

Yes.

If you're assigning a pointer the address of a stack allocated variable you need worry about when that variable goes out of scope, it will be destroyed! Then your pointer doesn't point to anything, and you will get some bad seg-fault type error messages at run time (meaning the program crashes).

With dynamic allocation it is common to leak memory, which when done to excess can cause your application to crash also. I only don't recommend dynamic allocation because you must keep track of the pointer and properly delete it, and with your current ideas a smart pointer is totally superior for that.

But in theory/practice you could copy an array of pointers to stack allocated objects and use them etc. As long as you make sure those variables don't go out of scope...

Or you could dynamically allocate and delete them.

smart pointers automatically delete the dynamically allocated variable when it goes out of scope.

The standard library has a smart pointer type, it's the std::auto_ptr<> BUT you can't put those in the STL containers for some lame reason. Thus, many opt to use the boost library's boost::shared_ptr<>.

I feel it is also important to note that programs often have limited stack space--with a limit of around 1 MB being common (as far as I know). Dynamically allocating memory uses the "heap" instead of the "stack" which will give you a much greater amount of memory to use.

Pointers are interesting (as you've realized). There is no way to tell from a pointer whether it should be deleted or not. For instance consider the following

Object o, * optr = &o;

// Some place later in your code
std::vector<Object *> optrs;
optrs.push_back(optr); // this should definitely *not* be deleted
optrs.push_back(new Object()); // this *must* be deleted

Now you've got a container that holds two types of pointers and you've no way to distinguish between them.

Smart pointers can help this to a certain extent but they do not completely remove the issue. I think that if you want to be safe you need to make a decision about the design of your code. Either
A) decide that pointers in containers should *never* be deleted and any scope inserting them should be responsible for deleting them. OR
B) Only ever insert by way of container.push_back(new Object()) and *always* delete the objects when they are removed from the container.

Each approach has its drawbacks and you need to decide which is acceptable for your situation.

So why aren't you using std::vector<DNA> again ?

using pointers because the vector will eventually reside within a class of its own with many other functions that will need to manipulate the data within the vector. Thats all achieved a little easier with pointers.

Many thanks everyone for your help, managed to sort it out and learned quite a bit in the process. Im still researching smart pointers but they seem more complicated than normal pointers, if such a thing is even possible.

Cheers.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.