I'm trying to delete everything from a std::vector by using the following code
vector.erase( vector.begin(), vector.end() );
but it doesn't work.
Update: Doesn't clear destruct the elements held by the vector? I don't want that, as I'm still using the objects, I just want to empty the container
I think you should use std::vector::clear:
vec.clear();
EDIT:
Doesn't clear destruct the elements
held by the vector?
Yes it does. It calls the destructor of every element in the vector before returning the memory. That depends on what "elements" you are storing in the vector. In the following example, I am storing the objects them selves inside the vector:
class myclass
{
public:
~myclass()
{
}
...
};
std::vector<myclass> myvector;
...
myvector.clear(); // calling clear will do the following:
// 1) invoke the deconstrutor for every myclass
// 2) size == 0 (the vector contained the actual objects).
If you want to share objects between different containers for example, you could store pointers to them. In this case, when clear is called, only pointers memory is released, the actual objects are not touched:
std::vector<myclass*> myvector;
...
myvector.clear(); // calling clear will do:
// 1) ---------------
// 2) size == 0 (the vector contained "pointers" not the actual objects).
For the question in the comment, I think getVector() is defined like this:
std::vector<myclass> getVector();
Maybe you want to return a reference:
// vector.getVector().clear() clears m_vector in this case
std::vector<myclass>& getVector();
vector.clear() should work for you. In case you want to shrink the capacity of the vector along with clear then
std::vector<T>(v).swap(v);
vector.clear() is effectively the same as vector.erase( vector.begin(), vector.end() ).
If your problem is about calling delete for each pointer contained in your vector, try this:
#include <algorithm>
template< typename T >
struct delete_pointer_element
{
void operator()( T element ) const
{
delete element;
}
};
// ...
std::for_each( vector.begin(), vector.end(), delete_pointer_element<int*>() );
Edit: Code rendered obsolete by C++11 range-for.
Use v.clear() to empty the vector.
If your vector contains pointers, clear calls the destructor for the object but does not delete the memory referenced by the pointer.
vector<SomeClass*> v(0);
v.push_back( new SomeClass("one") );
v.clear(); //Memory leak where "one" instance of SomeClass is lost
Is v.clear() not working for some reason?
If you keep pointers in container and don't want to bother with manually destroying of them, then use boost shared_ptr. Here is sample for std::vector, but you can use it for any other STL container (set, map, queue, ...)
#include <iostream>
#include <vector>
#include <boost/shared_ptr.hpp>
struct foo
{
foo( const int i_x ) : d_x( i_x )
{
std::cout << "foo::foo " << d_x << std::endl;
}
~foo()
{
std::cout << "foo::~foo " << d_x << std::endl;
}
int d_x;
};
typedef boost::shared_ptr< foo > smart_foo_t;
int main()
{
std::vector< smart_foo_t > foos;
for ( int i = 0; i < 10; ++i )
{
smart_foo_t f( new foo( i ) );
foos.push_back( f );
}
foos.clear();
return 0;
}
Adding to the above mentioned benefits of swap(). That clear() does not guarantee deallocation of memory. You can use swap() as follows:
std::vector<T>().swap(myvector);
If your vector look like this std::vector<MyClass*> vecType_pt you have to explicitly release memory ,Or if your vector look like : std::vector<MyClass> vecType_obj , constructor will be called by vector.Please execute example given below , and understand the difference :
class MyClass
{
public:
MyClass()
{
cout<<"MyClass"<<endl;
}
~MyClass()
{
cout<<"~MyClass"<<endl;
}
};
int main()
{
typedef std::vector<MyClass*> vecType_ptr;
typedef std::vector<MyClass> vecType_obj;
vecType_ptr myVec_ptr;
vecType_obj myVec_obj;
MyClass obj;
for(int i=0;i<5;i++)
{
MyClass *ptr=new MyClass();
myVec_ptr.push_back(ptr);
myVec_obj.push_back(obj);
}
cout<<"\n\n---------------------If pointer stored---------------------"<<endl;
myVec_ptr.erase (myVec_ptr.begin(),myVec_ptr.end());
cout<<"\n\n---------------------If object stored---------------------"<<endl;
myVec_obj.erase (myVec_obj.begin(),myVec_obj.end());
return 0;
}
class Class;
std::vector<Class*> vec = some_data;
for (unsigned int i=vec.size(); i>0;) {
--i;
delete vec[i];
vec.pop_back();
}
// Free memory, efficient for large sized vector
vec.shrink_to_fit();
Performance: theta(n)
If pure objects (not recommended for large data types, then just
vec.clear();
Related
I have this class:
class aa
{
public:
int i = 0;
~aa(){
std::cout << "killin in the name of" << std::endl;
}
};
And I want to make a vector of this class. First I thought o reserving the needed size:
int main()
{
std::vector<aa> vec;
vec.reserve(2);
vec[0] = *(new aa());
vec[1] = *(new aa());
//use the vector
vec.clear();
return 0;
}
But the destructor was not called.
On the other side, when I fill the Vector using push_back
int main()
{
std::vector<aa> vec;
vec.push_back(*(new aa()));
vec.push_back(*(new aa()));
//use the vector
vec.clear();
return 0;
}
I actually get the destructor called.
Why?
A std::vector already does this memory management for you.
When you use an std::vector with simple classes like this, you do not need any new or delete calls.
reserve
Under the hood, reserve is just making sure that a chunk of memory is preallocated to hold the specified number of member variables.
resize
Under the hood, resize will actually create n new objects. You do not need to explictly call new.
Your example
The code *(new aa()) will create a new aa object on the heap. When you write vec[0] = *(new aa()); it will attempt to copy the contents of your new object to the object that lives in the address vec[0]. Thus there are 2 distinct objects alive at this point in time ... one object vec[0] at one place in memory, and one object elsewhere in memory.
What's worse is that you have now called new and never deleted that object. You thus have a memory leak.
What you probably want
Almost certainly, what you will want one of these scenarios.
Create a vector, and then resize it to have n elements. Then use those elements:
int main() {
std::vector<aa> vec;
vec.resize(2);
vec[0].i = ...;
vec[1].i = ...;
//use the vector
return 0;
}
push_back elements when you want to add things
int main() {
std::vector<aa> vec;
vec.push_back(aa()); // Creates a new aa instance and copies into the vector
aa obj;
vec.push_back(obj); // Copies the existing object's data into a new object in the vector.
//use the vector
return 0;
}
The destructor of vector will delete all of the memory appropriately. No need to explicity clear in this example.
There are more advanced ways that you can use vector, but until you understand this code, you probably should just stick to these basics.
Is there a recommended strategy for dealing with external libraries which expect manually managed raw pointers. For example a method which takes a vector of pointers:
ALibraryFunc(std::vector<ALibraryData*> p);
so generally you'd create your vector with something like:
std::vector<ALibraryData*> myVec;
for(...)
{
myVec.push_back(new ALibraryData(args));
}
//and then
ret = ALibraryFunc(myVec);
//and then
for(auto &a:myVec)
{
delete a;
}
myVec.clear();
I'd much prefer to use smart pointers but the library will not take them. This leaves me wondering if something like this is more stinky than just doing it manually:
std::vector<std::unique_ptr<ALibraryData>> myVecUP;
std::vector<ALibraryData*> myVec;
for(...)
{
myVecUP.push_back(std::make_unique<ALibraryData>(args));
myVec.push_back(myVecUP.back().get());
}
//and then
ret = ALibraryFunc(myVec);
myVec.clear();
myVecUP.clear();
The second version seems safer in case of exceptions or mistakes but it does risk dangling pointers. Am i missing something obvious here? What do/would you do?
You can declare a small class which will own the vector of raw pointers, and delete the pointers in the destructor:
struct VecOwner {
std::vector<ALibraryData*> vec;
VecOwner(<some arguments>)
{
// fill the vector here
}
~VecOwner()
{
for(auto &a:vec)
delete a;
vec.clear();
}
};
you should be able to reuse the class in all places where you use the library.
You can use 'scope exit' idiom :
//open scope block
{
std::vector<ALibraryData*> myVec;
////////////////////////////////////////
struct MyVecRAIICleaner{
std::vector<ALibraryData*> * myVecPtr;
~MyVecRAIICleaner(){
if (myVecPtr) {
for(auto& a: *myVecPtr)
delete a;
myVecPtr->clear();
}
}
} myRAIICleaner = {&myVec};
////////////////////////////////////////
for(...)
{
myVec.push_back(new ALibraryData(args));
}
//and then
ret = ALibraryFunc(myVec);
/** You needn't below code. */
////and then
//for(auto &a:myVec)
//{
// delete a;
//}
//myVec.clear();
}// end scope block
EDIT:
I'm sorry, but Wojtek Surowka's answer is not exception safe or required extra try catch block in constructor.
I have two vectors and for some elements (not all) i need them to be connected ~ if i delete/change this element in one vector it should be removed/changed in both.
Something similar like pointers:
int r = 10;
int *p= &r;
*p = 3;
For example in next code it should change myvector2[0].a to 7.
#include <iostream>
#include <vector>
using namespace std;
struct elt {
int a, b, c;
};
int main()
{
vector<elt> myvector;
vector <elt> myvector2;
elt elt1 = {1,3,3};
myvector.push_back(elt1);
elt *elt2 = &elt1;
myvector2.push_back(*elt2);
myvector[0].a=7;
cout << myvector[0].a << endl; //7
cout << myvector2[0].a << endl; //1
return 0;
}
How can i make this possible? Please help!!!
As tgmath explained, the issue is that you wind up with two different objects in your vectors, as the standard containers store elements by value. I would recommend that you use shared pointers to properly maintain the lifetime of the objects (note this uses C++11 features):
#include <iostream>
#include <vector>
#include <memory>
struct elt {
int a, b, c;
};
int main()
{
std::vector<std::shared_ptr<elt>> myvector;
std::vector<std::shared_ptr<elt>> myvector2;
auto elt1 = std::make_shared<elt>(elt {1,3,3});
myvector.push_back(elt1);
myvector2.push_back(elt1);
myvector[0]->a=7;
std::cout << myvector[0]->a << std::endl; //7
std::cout << myvector2[0]->a << std::endl; //7
return 0;
}
Pointers and references (and iterators) to elements of std::vector are invalidated whenever the vector reallocates, which can happen during insertion. So you can only keep these if the vector is guaranteed not to reallocate for the lifetime of the pointer/reference. This can be achieved if you don't insert into the vector, or if you call reserve() on it before you start (and before you acquire the pointer/reference/iterator), extending its capacity so that no reallocations will be necessary.
If you can't guarantee that, your only option is to keep the index instead of a pointer/reference. Of course, you will also need access to the vector itself for this to work, but you should be able to keep a pointer or reference to it, e.g.
typedef std::pair<std::vector<elt>*, size_t> ReferenceIntoVector;
myvector2.push_back(*elt2); adds a copy of *elt2 into myvector2
This means that both vector have their own copy of the elt object. And both of them are distinct from elt1.
If you change the one in the first vector, the second does not change at all.
For this purpose yiu would need a std::vector<elt*> to have different pointers to the same object in different vectors.
First, there is no built in way to automatically remove an element from one vector if you happen to delete it from another.
In my opinion there are two different challenges here:
How can I update an element pointed to by one list to be updated in another?
How can I remove an element from one list, and have that removed from the other?
The first question is already answered in the other posts: Use std::shared pointers instead of your native pointers. They are just as fast and will take care of all the memory management for you.
Please note: That this approach will only work as long as you are only changing the value of the element pointed to by the shared pointer, and not what the shared pointer is pointing to.
In other words/code:
std::vector<std::shared_ptr<elt>> vec1, vec2;
// Insert some elements
vec1.push_back( std::make_shared( elt{ 1, 2, 3} );
vec2.push_back( vec1.back() );
vec1[0]->x = 5; // OK, updated in both vectors.
vec1[0] = make_shared(elt {3,2,1}); // Error: vec1[0] is pointing to a new object.
The other challenge is much harder, how can you automatically delete an element from both vectors. The short answer is "You can't", the slightly longer is, you can but not directly.
Approach 1: Setting deleted elements to nullptr.
This approach is a bit dirty an not something I would recommend as it requires all code that use either vector to check whether an element is nullptr.
// Encapsulate the object inside a `std::unique_ptr`
std::vector< std::shared_ptr< std::unique_ptr< elt >>> vec1, vec2;
// Adding elements are done similarly as before
vec1.push_back( std::make_shared( std::make_unique( elt{ 1, 2, 3} )));
vec2.push_back( vec1.back() );
// Now to delete a element you would do as follows
vec1[0]->reset(nullptr); // Flag this element as deleted
vec1[0]->erase( vec1.begin() ); // Remove element from vec1
// Now let us assume we are iterating through the other vector at a later time:
for (auto it = vec2.begin(); it != vec2.end(); ++it ) { // Using iterators makes the code cleaner.
if ( **it == nullptr ) { // If the unique_ptr == nullptr
it = erase(it);
else {
etl & the_value = ***it; // Yes you need all three, one for the iterator, one for the shared_ptr and one for the unique_ptr...
}
}
As you can see this quickly gets hairy. But if that is all you need it can work.
Approach 2: (The better in my opinion) Is to use the Observer/Observed Design Pattern.
In order to implement this pattern you will need to exchange your vector for another class. Let us make a simple example:
// First, create an interface describing all operations you want to be
// informed about.
template<class T>
class SharedElementListObserver {
protected:
void elementDeleted( const shared_ptr<T> & elem ) = 0;
}
template<class T>
class SharedElementList : public SharedElementListObserver<T> {
std::vector<std::shared_ptr<T>> data;
std::unordered_set<SharedElementListObserver*> observers;
public:
void push_back( const T & elem ) { data.push_back( std::make_shared<T>( elem )); }
void push_back( std::shared_ptr &sptr ) { data.push_back( sptr ); }
shared_ptr<T> operator[] (int index) {
return data[index];
}
shared_ptr<const T> operator[] (int index ) const {
return std::static_pointer_cast<const T>( data[index] );
}
// This will cause all instances of elem in all lists
// linked either directly and indirectly to this
// to be removed.
void delete( int idx ) {
if (idx >= 0 && idx < data.size() ) {
shared_ptr<T> temp = data[idx];
data.erase( data.begin() + idx );
for (auto observer : observers) {
observer->elementDeleted(temp);
}
}
}
// Link another list to this one to listen to deletions.
void link( SharedElementListObserver* observer ) {
if (observer == this) return;
else if (observers.insert(observer).second) {
observer->observers.insert(this);
}
}
// Unlink previously linked observer.
void unlink(SharedElementListObserver* observer) {
observer->observers.erase(this);
this->observers.erase(observer);
}
protected:
void elementDeleted( shared_ptr<T> & elem ) {
for (int i = 0; i < data.size(); ) {
if (data[i] == elem)
delete(i); // Not infinite loop, because of test above.
else
i++;
}
}
// You also need to write an operator=, a copy-constructor and a destructor
// that ensures that there are no dead observers in the observers list.
};
Depending on your assumptions this class can be implemented in a number of different ways. Some probably simpler than what I just did.
Please let me know if there are any errors in the above code.
I have a vector of object pointers
std::vector<Element*> elements;
When iterating through the vector, I would like to double dereference the iterator in order to call the object's methods.
std::cout << (*it)->getName() << std::endl;
This leads to a segfault. The relevant code is below.
I am thinking that the problem is with how I am initializing the vector, because I could move the for-loop to be in the method initialize() and it works fine. In takeTurn(), the vector is of the appropriate size and the pointers contain the correct addresses. Does this mean that the objects being pointed to are being prematurely destroyed?
main.cpp:
#include <vector>
#include <iostream>
#include "Element.h"
std::vector<Element*> elements;
void initialize() {
Element ice = Element("ice",1);
Element fire = Element("fire",2);
elements.push_back(&ice);
elements.push_back(&fire);
}
void takeTurn() {
std::vector<Element*>::iterator it;
for(it = elements.begin(); it != elements.end(); ++it) {
std::cout << (*it)->getName() << std::endl;
}
}
int main() {
initialize();
takeTurn();
return 0;
}
Element.h:
#include <string>
class Element {
public:
Element(std::string name, int id);
int getID() { return id_; }
std::string getName() { return name_; }
private:
int id_;
std::string name_;
};
Element.cpp:
#include "Element.h"
Element::Element(std::string name, int id) {
name_ = name;
id_ = id;
}
Your initialize function is broken. You create local objects, and then push their addresses onto the vector. But when the function returns, those objects are destroyed, and the pointers are no longer valid. The simplest fix, unless you need polymorphism, is to just make a vector of Element objects, instead of pointers.
std::vector<Element> elements;
...
elements.push_back(Element("ice",1));
elements.push_back(Element("fire",2));
If you need polymorphism, then use smart pointers.
std::vector<std::unique_ptr<Element>> elements;
...
elements.push_back(std::unique_ptr<Element>(new Element("ice",1)));
elements.push_back(std::unique_ptr<Element>(new Element("fire",2)));
If you were to continue to use raw pointers, then you would need some way to ensure the persistence of the objects, perhaps by allocating them with new. You would then need to ensure you call delete on each of those pointers you are done with them. I do not recommend this route.
You are passing pointers to local variables to the vector here:
Element ice = Element("ice",1);
Element fire = Element("fire",2);
elements.push_back(&ice);
elements.push_back(&fire);
When you exit the function, ice, and fire cease to exist, so you are left with dangling pointers.
The solution to this problem depends on whether you really need a vector of pointers. It might be simpler to have std::vector<Element>:
std::vector<Element> elements;
then
elements.push_back(Element("ice",1));
elements.push_back(Element("fire",2));
You push dangling pointers into your vector:
void initialize() {
Element ice = Element("ice",1);
Element fire = Element("fire",2);
elements.push_back(&ice);
elements.push_back(&fire);
}
here ice and fire is local variable. You push the address to the vector, then as final } is reached both get destroyed. Later when you rereference this invalid pointer behavior is undefined.
Your vector is storing pointers to local variables that are created on the stack. When the function is finished, the memory occupied by these variables will be reclaimed. If you try to access the memory, you will get a segfault.
void initialize() {
Element ice = Element("ice",1); // Local variable.
Element fire = Element("fire",2); // Local variable.
elements.push_back(&ice);
elements.push_back(&fire);
} // Ice and fire disappear.
Allocate the memory for the elements on the heap:
void initialize() {
Element *ice = new Element("ice",1);
Element *fire = new Element("fire",2);
elements.push_back(ice);
elements.push_back(fire);
}
Remember to free the memory when you are finished!
typedef std::vector<Element *>::iterator EIter;
for (EIter it = elements.begin(); it != elements.end(); ++it) {
delete *it;
}
I am working on a library where users should be able to use static global instances. These instances (being run before main) register themselves in another global vector which can then be used...
Currently, it goes somewhat like this...
class A;
std::vector<A*> v;
class A {
public:
A (int i) : i(i) {
v.push_back(this);
}
int get () const {
return this->i;
}
private:
int i;
};
A a(1);
A b(2);
int main ()
{
for (A* const& c : v)
std::cout << c->get() << std::endl;
for (std::vector<A*>::iterator i = v.begin(); i != v.end(); i++)
delete *i;
return 0;
}
However, I'm afraid this code will leak... even more so when I don't want users to explicitely delete the contents of the vector (they'll forget it anyway), it should happen automatically at the end of main.
Are there other solutions? I wanted to use a vector of std::unique_ptr, but apparently they don't work that way...
Your code doesn't leak. The only thing that allocates memory there is std::vector, and it cleans itself up on destruction.
a and b are correctly destroyed and released at the end of execution.
You shouldn't delete things that weren't allocated with new.
Also, you are relying on v being initialised before a and b are constructed. You should lazily initialise v instead (see below).
std::vector<A*>& global_v()
{
static std::vector<A*> v;
return v;
}
// use global_v() instead of v in the A constructor.
To get what you want, just remove the loop that deletes those objects.
Here's your code running in action with the loops removed and some debug output added. Notice that both objects are destroyed correctly.