"Right" Way to Deallocate an Std::Vector Object

Right way to deallocate an std::vector object

The simplest and most reliable way to deallocate a vector is to declare it on the stack and simply do nothing.

void Foo() {
std::vector<int> v;
...
}

C++ guarantees that the destructor of v will be called when the method executes. The destructor of std::vector will ensure any memory it allocated is freed. As long as the T type of the vector<T> has proper C++ deallocation semantics all will be well.

Deallocating objects stored in a vector?

It depends on how vector is defined.

If maps is a vector<myClass*> you delete each element with something similar to:

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

If maps is a vector<myClass> I don't think you need to delete the individual elements.

How to correctly deallocate a c++ vector?

My thought process is that I'm using a Set *aSet = new Set; in my main class and since an int is not an object, it's not being freed when I call list.clear(). Is this right? How would I go about deleting the memory correctly?

No. To delete the memory you allocate correctly you need to call delete:

Set *aSet = new Set;

delete aSet;

However manually managing memory like this is difficult and error prone. You should prefer alternatives. The first is that you should not use dynamic allocation at all. You should simply use automatic variables:

Set aSet;
// no delete required. Variable destroyed/deallocated when it goes out of scope.

If you really do need dynamic allocation you should use smart pointers.

std::unique_ptr<Set> aSet(new aSet);

Smart pointers implement RAII for dynamic allocation so you don't have to do it manually.

In some rare circumstances you may actually need to do dynamic allocation manually, but that's an advance topic.


std::vector<T>::clear() is not required to deallocate the vector's memory. You can use the C++11 member function shrink_to_fit(), or you can use the swap trick:

std::vector<int> list;

...

std::vector<int>(list).swap(list);

Also you really shouldn't be using a pointer to a vector. A vector uses RAII to manage dynamic memory for you. When you use a pointer to a vector you no longer have the benefit of not manually managing the resource yourself.

How do I deallocate contents of a vector upon its destruction?

This is why we have smart pointers.

{
std::vector<std::unique_ptr<cls>> vec;

// C++14 will allow std::make_unique
vec.emplace_back(std::unique_ptr<cls>(new cls(5)));
}

When the vector goes out of scope, the destructors of the unique_ptrs will be called and the memory will be deallocated.

In your case, with the raw pointers, you'd have to delete whatever you created with new manually:

// Something along the lines of this.
for (auto&& elem : vec) {
delete elem;
}

Also, where is memory allocated for the vector as well as the contents if I declare vector as:

You're allocating the vector with new, so it'll be on the heap.

C++ delete vector, objects, free memory

You can call clear, and that will destroy all the objects, but that will not free the memory. Looping through the individual elements will not help either (what action would you even propose to take on the objects?) What you can do is this:

vector<tempObject>().swap(tempVector);

That will create an empty vector with no memory allocated and swap it with tempVector, effectively deallocating the memory.

C++11 also has the function shrink_to_fit, which you could call after the call to clear(), and it would theoretically shrink the capacity to fit the size (which is now 0). This is however, a non-binding request, and your implementation is free to ignore it.

How does std::vector in c++ gets deallocated by default

There are several STL implementations, they diff from each other, but they are similar. Let's take the latest version of GCC's libstdc++ as an example:

The destructor of std::vector, all the elements in the vector are destroyed via calling std::_Destroy

      ~vector() _GLIBCXX_NOEXCEPT
{
std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
_M_get_Tp_allocator());
_GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC;
}

The vector has a base class:

  template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
class vector : protected _Vector_base<_Tp, _Alloc>

For the memory used in the vector itself, it is destroyed in _M_deallocate in the base class, which will call the deallocate at last:

      ~_Vector_base() _GLIBCXX_NOEXCEPT
{
_M_deallocate(_M_impl._M_start,
_M_impl._M_end_of_storage - _M_impl._M_start);
}
      void
deallocate(_Tp* __p, size_type __n __attribute__ ((__unused__)))
{
#if __cpp_sized_deallocation
# define _GLIBCXX_SIZED_DEALLOC(p, n) (p), (n) * sizeof(_Tp)
#else
# define _GLIBCXX_SIZED_DEALLOC(p, n) (p)
#endif

#if __cpp_aligned_new
if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
{
_GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n),
std::align_val_t(alignof(_Tp)));
return;
}
#endif
_GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n));
}

_GLIBCXX_OPERATOR_DELETE is a macro, we can regard it as delete

fully deallocating the memory of a std::vector container

Yes, it is correct, provided mvMyObjectVector_ptr has been allocated using new.

Additionally, MyObject needs to satisfy certain requirements before it can be used with std::vector.

The call to clear() is redundant and can be omitted.

Some likely reasons for the SIGABRT include:

  • mvMyObjectVector_ptr hasn't been allocated using new;
  • MyObject violates the Rule of Three;
  • the class the contains the vector violates the Rule of Three.

How to correctly deallocate or delete a c++ vector?

The only way to really get rid off unused memory in a std::vector<> pre C++11 is to swap it with an empty vector: vector<int>().swap(myvec). In C++11 you have a member function shrink_to_fit which often is implemented as the swap idiom just mentioned.

How to remove object from a vector if it was deleted

From your sample code, I assume your vector is defined somewhat like this:

std::vector<YourType*> entities;

Therefore, your vector does not contain YourType objects, but pointer to YourType. That is, the elements the vector manages are the pointers, not the pointed objects.

Thus when you do this delete entities[x + y * width]; you indeed delete the YourType instance, but the pointer still exists and it sill in your vector.

It might be easier to visualize if you decompose that statement to the equivalent 2 lines:

YourType * pointer = entities[x + y * width];
delete pointer;

To actually remove the pointer from the vector, you need to say so:

entities.erase(entities.begin() + x + y * width);

This would remove the pointer from the array (also shifting all things past that index). You still need to do the delete yourself as, again, the vector is only managing the pointer, not the YourType.


Note that unless you have a good reason, you should probably not store the pointer in the vector, but the object itsself. That would remove your confusion:

std::vector<YourType> entities;

// deleting a YourType:
entities.erase(entities.begin() + x + y * width);

No delete or new anymore, because the object is directly in the vector. So the vector manages it for you instead of just managing the pointer and letting you deal with the pointed object.


Update after question edit:

In your case, you do have a good reason, because you actually store a non-owning pointer. So it might make sense that entities and projectiles store pointers, so they actually point at the same objects.

So both vectors will manage their pointers, but you have to think of how the lifecycle of those two pointers (the one from entities and the one from projectiles) interact with the object itself.

Deleting the object will not get rid of the pointers, in neither of the arrays.

How to properly clean up elements from vectors of object pointers

you mentioned in the comments that the objects will have other pointers to them. this sounds like std::shared_ptr<A> to me. this way you can have other pointers to your A objects without memory leaking issues. (std::shared_ptr comes with a small(!) performance cost, but you should not worry about it for now).
additionally i changed your passage to delete/erase your element from the vector. be aware that the A objects are still alive IF there are other instances keeping a std::shared_ptr<A> copy to it (but thats a good thing).

here is the code:

#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>

class A
{
public:
A(int i) { x = i; }
int x;
};

int main()
{
std::vector<std::shared_ptr<A>> Vec;
Vec.emplace_back(std::make_shared<A>(5));
Vec.emplace_back(std::make_shared<A>(4));
Vec.emplace_back(std::make_shared<A>(3));

std::cout << "Size before = " << Vec.size() << std::endl;

Vec.erase(
std::remove_if(std::begin(Vec),std::end(Vec), [](auto&& ptr){ return ptr->x == 3;}),
std::end(Vec));

std::cout << "Size after = " << Vec.size() << std::endl;
for (auto&& a : Vec)
{
std::cout << a->x << std::endl;
}

return 0;
}


Related Topics



Leave a reply



Submit