copying elements from vector to another one - c++

I have two vectors of pointers: arr that contains some elements already and temp, the new vector I want to copy specific elements from arr to. For example I'd like to copy second element of arr to be copied into temp and deleted from arr. How can it be done?
I tried this, but it's not good:
void deleteobject(vector < figure3d *> &arr,int index,vector < figure3d *> &temp)
{
vector < figure3d * > :: iterator i=arr.begin();
temp.insert(temp.begin(),*i);
delete *i;
arr.erase(i);
temp[0]->print();
}

You shouldn't delete the object you're copying since you want to keep it in temp - just erase it from arr.

arr.begin() gives you an iterator pointing to the first element, so if you want the second element, you should advance i one:
++i;
If you want the indexth element, you should advance i by index:
i += index;
Storing raw pointers in a vector, and having to remember to delete them when removing them from the vector is a memory leak waiting to happen. And ass molbdnilo mentioned in another answer, you actually have a memory handling error since you're deleting the object that temp has a pointer to.

From what I understand you want to copy an element at specified index (argument index) and remove it from vector temp. This function could look simple like this:
void deleteobject(std::vector<figure3d*> &arr, int index, std::vector<figure3d*> &temp)
{
temp.insert(temp.begin(), arr[index]);
arr.erase(arr.begin() + index);
}
In this case, you don't copy the object itself, but only a reference to it - thus you don't need to free the memory where this object is stored.
Also note that in your function you call delete *i; which frees the memory where the object pointed by i is stored - and the pointer that stored in arr becomes invalid (dangling pointer), because it points to memory that was freed already.
And I also suggest you to use vector of objects rather than vector of pointers to objects - although elements get copied, it's usually fast enough and there is no troublesome memory management connected with it. And in case there is a good reason why you use vector of pointers ( When to use pointers in C++ ),
I suggest you to use vector of smart pointers instead: if you have TR1 or C++11 support, use std::shared_ptr, otherwise use boost::shared_ptr ( Where is shared_ptr? )

This looks like a job for !
something like this is what I would do:
Class removePredicate{
Public:
bool operator() (figure3d** item) {
//remove logic goes here
}
};
remove_copy_if(arr.begin(), arr.end(), back_inserter(tmp), not1(removePredicate));
This will copy all the elements that you want to remove into tmp. The to actually remove them from arr it's just a simple application of the remove-erase idiom:
erase(remove_if(arr.begin(), arr.end(), not1(removePredicate)), arr.end());
There's probably a way to combine these two steps into one line but you run the risk of losing readability at point.

Related

Deleting a dynamic array of pointers in C++

I have a question concerning deleting a dynamic array of pointers in C++. Let's imagine that we have a following situation:
int n;
scanf("%d", &n);
Node **array1 = new Node*[n];
/* ... */
where Node is a certain structure defined beforehand. Suppose that after allocation with the new operator, we change the content of the array1 (but we do not delete anything!). What is the proper way to delete the array1 and all its content if there is a possibility of repeated pointers in the array (without sorting them or inserting into the set, in linear time)?
Using this allocation:
Node **array1 = new Node*[n];
The contents of array1 are undefined. Each element is a Node*, and because the memory is uninitialized, the value could be anything.
Allocating an array of pointers does not construct objects of the pointed-to class.
So whatever pointers you put into the array, the objects they point to need to be constructed and destructed elsewhere.
So to answer your question, the proper way to delete array1 is
delete[] array1;
However, note that this will not result in destructors being called for each Node* - you should deal with whatever you put into the array before you delete the array.
EDIT:
I was confused by the original question, which mentioned "change the value" in the array, as if there was a valid value in the array as allocated in your example.
BUT... now that I understand you want to keep track of the pointers for deletion later, perhaps you can just create another array for that purpose where each pointer exists only once. So you have the array you currently have above, which contains pointers to nodes that might be repeated, for whatever purpose you're using it. Then you have another array for the express purpose of managing the deletion, where each pointer occurs only once. It should be easy enough to set something like nodeCleanupArray[i] = pNewNode right after pNewNode = new Node(), then you can blast through that array in linear time and delete each element. (Which means you wouldn't bother inspecting the elements in array1, you'd rely on nodeCleanupArray for the cleanup)
There are MANY solutions to this sort of problem, but the most obvious choice would be to change it to use
std::vector< std::shared_ptr<Node> >
Now you will have a reference counted pointer without writing any code, and an "array" that doesn't need to know it's predefined size.
You can of course implement a reference counted object within Node, or your own container object to do the same thing, but that seems like extra hassle for little or no benefit.
Try mark and sweep :) You are trying to implement a managed environment.
Here is an example:
struct Node
{
...
bool marked;
Node() : marked(false)
{}
};
Now delete:
void do_delete(Node **data, size_t n)
{
size_t uniq = 0;
Node **temp = new Node*[n];
for (size_t i = 0; i < n; i++)
{
if (data[i] && !data[i]->marked)
{
data[i]->marked = true;
temp[uniq++] = data[i];
}
}
for (i = 0; i < uniq; ++i)
{
delete temp[i];
}
delete[] temp;
delete[] data;
}
The way I'd do this is have a reference counters and have a Node::deref method that would delete the node itself when reference count is 0. When iterating through the list of nodes, calling node->deref will not actually delete the object until the last Node reference in the array.
What is the proper way to delete the array1 and all its content
You show a single allocation; new Node*[n]. This allocation confers on the program the responsibility to call delete [] whatever_the_return_value_was. This is only about deleting that one allocation and not about deleting 'all its content'. If your program performs other allocations then the program needs to arrange for those responsibilities to be handled as well.
if there is a possibility of repeated pointers in the array
Well it would be undefined behavior to delete a pointer value that is not associated with any current allocation, so you have to avoid deleting the same pointer value more than once. This is not an issue of there being a single correct way, but an issue of programming practices, design, etc.
Typically C++ uses RAII to handle this stuff automatically instead of trying to do what you want by hand, because doing it by hand is really hard to get right. One way to use RAII here would be to have a second object that 'owns' the Nodes. Your array1 would then simply use raw pointers as 'non-owning' pointers. Deleting all the Nodes then would be done by letting the Node owning object go out of scope or otherwise be destroyed.
{
// object that handles the ownership of Node objects.
std::vector<std::unique_ptr<Node>> node_owner;
// your array1 object that may hold repeated pointer values.
std::vector<Node*> array1;
node_owner.emplace_back(new Node); // create new nodes
array1.push_back(node_owner.back().get()); // put nodes in the array
array1.push_back(node_owner.back().get()); // with possible duplicates
// array1 gets destroyed, but it's contents do not, so the repeated pointers don't matter
// node_owner gets destroyed and destroys all its Nodes. There are no duplicates to cause problems.
}
And the destruction does occur in linear time.

deleting an element in a vector of pointer

I just want to make sure if this is the right way to delete an allocated memory where there exist an element in the vector that pointing to that object;
vector<Fruit*> temp;
let say if the sixth element in the vector is pointing to the object that I want to delete.
Fruit* a = temp[5];
temp.erase(temp.begin()+5);
delete a;
is this right? thx
The Kerrek's suggestion is of course OK:
delete temp[5];
temp.erase(temp.begin() + 5);
I'm writing an answer, however, to suggest you think about smart pointers. Here's an example:
std::vector<std::shared_ptr<Fruit>> v;
// add some elements
v.erase(temp.begin() + 5);
In this case, there's no memory leak, because shared_ptr destruction deletes the object owned by it, or decreases the number of references properly. If there's no shared ownership involved, you can just use unique_ptr. boost::ptr_vector might also come in handy.

Lifetime of element removed from global vector

I basically have a
vector<Object> vec_;
as a class member in a cpp class. At a certain class function this vector will be filled with "Objects" just like this:
vec_.push_back(Object());
At a later time I iterate through the vector elements and keep a pointer to the best element. Then the vector is cleared as shown in the following:
Object* o_ptr = &(vec_[0]);
for (unsigned int i = 1; i < vec_.size(); i++) {
if (o_ptr->getCost() > vec_[i].getCost()) {
o_ptr = &(vec_[i]);
}
vec_.clear();
Now my question is: What happens to the objects removed from the vector? Is their lifetime over as soon as the they are removed from the vector? And does the pointer also point to empty space then?
And if not when does the lifetime of these objects end?
Regards scr
When vector.clear() is called (or when the vector is destructed) all objects contained with the vector will be destructed (as in this case they are objects and not raw pointers), leaving o_ptr as a dangling pointer.
Note that caching the address (or iterator) of an element in vector is dangerous, even without a call to clear(). For example, push_back() could result in internal reallocation of the vector, invalidating the cached address (or iterator).
What happens to the objects removed from the vector?
They are destructed.
Is their lifetime over as soon as the they are removed from the vector?
Yes.
Does the pointer also point to empty space then?
Yes it does. If you want to save the object, make a copy of it before clearing the vector.
It's also important to note that certain vector operations might leave pointers pointing to nothing even if the vector is not cleared. Specifically resizes, which typically involve a reallocation. It's generally best to store references to vector elements by index, since you will always be able to get the element via the index (whereas a pointer may be invalidated after certain operations).
The subscript operator, applied to vectors, returns a reference and does not make a copy.
The objects are owned by the vector and .clear() indeed removes them.
In addition, pointing to the objects stored in a std::vector is a bit dangerous. If you push new elements to the vector, at some point the vector might need to allocate more memory - which is likely to copy all the previous elements to a different address using their copy constructor (hence invalidating your pointers).
So: Use integer indices with std::vector instead of pointers, unless you know that you won't be pushing beyond the reserved capacity (which you can assure using .reserve()).
(Also while we're at it, make sure not to confuse the vector's internal buffer size with .size(), which is simply the number of actual elements stored).
The best way to track the lifetime of an object is to add a printf to both the constructor and destructor.
class MyObject
{
public:
MyObject()
{
printf("MyObject constructed, this=%p\n", this);
}
~MyObject()
{
printf("MyObject destructed, this=%p\n", this);
}
};

New Operator With Vectors

These questions are relatively straight forward. When using vectors, should I use the new operator when pushing back a new element? And which release method should I call? Here's what I mean:
// Release method: 1.
void ReleaseMethodOne( vector< int * > &ThisVector )
{
// Clear out the vector.
ThisVector.clear( );
return;
}
// Release method: 2.
void ReleaseMethodTwo( vector< int * > &ThisVector )
{
// Clear out the vector.
for( unsigned uIndex( 0 ); uIndex < ThisVector.size( ); uIndex++ )
{
delete ThisVector.at( uIndex );
}
return;
}
int main( )
{
vector< int * > Vector;
// Add a new element.
Vector.push_back( new int( 2 ) );
// More code...
// Free the elements before exiting. Which method should I call here?
ReleaseMethodOne( Vector ); // This one?
ReleaseMethodTwo( Vector ); // Or this one?
return 0;
}
I've started learning vectors not long ago and the book I was learning from said that the vector's clear( ) method called each of the elements destructor. Do this apply to the new operator?
STL containers store copies of the objects you give to them, pointers in your example. They never release any memory you explicitly allocated. You have to deallocate that memory yourself, so the second "release" method should be used.
Of course, you don't need to new every int. Just use vector<int> instead - you won't have to deal with manual memory management at all.
The clear method will indeed call destructors. However, your vector is storing pointers, and the destructor for pointers is a trivial no-op. It does not call delete.
Therefore, simply calling clear will not free the memory for all the int objects you allocated with new. You need to delete them.
If you use a smart pointer instead of an ordinary pointer, then the pointed-at objects will get freed at the appropriate time without you having to do anything special.
For what you are doing there you would need to use ReleaseMethodTwo. What it means by saying that it calls the element's destructor is that contained classes (not contained pointers) will lose scope and have their destructors called.
No STL container will ever call delete for you, so far as I know. If you allocate and pass in a pointer, you will need to deallocate.
You should use ReleaseMethodTwo(), because if you've allocated the memory, then it's your responsibility to delete it.
std::vector::clear() only erases the elements from the vector. It doesn't call delete on the elements being erased!
As answered by others, vector does call the destructor of each element. In your case, the elements are pointers and hence it will not free the memory.
For your application, the best choice is to use a reference counting smart pointer like boost:shared_ptr. Once there are no more references pointing to the elements (like the example you had written), the memory will be freed automagically.
PS: Do not use a "non-reference counting" smart pointer like std::auto_ptr with vector.
if you are using vactor<int *> than you'll have a vector of pointers and you have to allocate memory for each elements and free this memory yourself also. It doesn't make much sense to use vector of pointers unless the size of type you want to store in the vector is quite big.
Actually when you do vector<T>::push_back(val) is it going to store a copy of val using a copy constructor T::T(T &orig) and call destructor for all elements when you do clear()

C++ Memory allocation question involving vectors

vector< int > vect;
int *int_ptr = new int(10);
vect.push_back( *int_ptr );
I under stand that every "new" needs to be followed by a "delete" at some point but does the clear() method clean this memory?
What about this method of doing the same thing:
vector< int > vect;
int int_var = 10;
vect.push_back( int_var );
From what I understand, clear() calls the variables destructors, but both vect.push_back() methods in this example push an object on the vector, not a pointer. so does the first example using an int pointer need something other than clear() to clean up memory?
The first method leaks because the vector never takes ownership of the allocated pointer. In fact, it doesn't contain a pointer at all, only a copy of the value.
The second method does not leak, as no memory is dynamically allocated (except internally in the vector -- it will handle that memory itself).
When you push_back on a vector, you add a copy of the data to the vector. Therefore, in both cases, the original data still needs to be freed. In the first case, you need to delete it; in the second, it will be "freed" by the stack pointer as it goes out of scope.
Vectors make copies on push_back. Since a pointer is 'just another variable' (but one that happens to point to memory), when you push_back an integer pointer that has been previously allocated, you copy the pointer's value into the vector, causing a potential dangling pointer, since there will be two pointers pointing at the same spot in memory.
In your first example, you would need to delete the memory manually. One strategy I've used in the past for meddling with graph classes is to have something like this (vast amounts of stuff redacted due to being at work and typing quickly):
class graph //quick-format
{
vector<node*> nodes;
add_node(node n)
{
node *temp = new node;
*temp = n;
nodes.push_back(temp)
}
~graph()
{
for(int i = 0; i < nodes.size(); i++)
delete nodes[i];
}
};
As a caveat, graph's copy semantics will have to be examined. As it stands, it will result in deleting previously-free'd memory. The advantage is that you can always have the same set of nodes hanging around. Caveat Emptor, like any direct memory usage..
However, if you simply push a non-pointer variable, there is no possibility of memory leaking from your end. Possibly the vector will leak, but... that is practically impossible at this point in the maturity of the tools.