Service Life of STL Container Elements

I am trying to save objects in a stl container (in this case a vector) and I want the container to destroy the objects when it is destroyed, but I can not fully figure out the details.

One of the ways that I don't want to do this is simply using it as

vector<MyClass> myVec; myVec.push_back(MyClass(...)); 

due to the fact that the constructor is called twice (once in the code above, then copy the constructor in the vector) and the destructor once.

The most direct alternative is to use pointers to store dynamically allocated objects, but then the MyClass destructor will not be called when the vector is destroyed. Saving auto_ptr instead of regular pointers gives an error with myVec.push_back (...) .

In any case, in order to avoid the first option, when the container destructor calls the element destructor?

Thank you for your responses!

EDIT

Consider a similar problem; how to implement a container that owns objects using an abstract base class. The unique pointer (Boost unique_ptr) does not have copy constructors, so do not use it directly.

 class A {}; // Abstract base class. class B : public A {}; // Sub class. ... vector<A *> vec; vec.push_back(new B()); // At destruction of vec, destroy elements left in container. 
+4
source share
5 answers

An alternative not mentioned earlier is the Boost Pointer Container Library .

Boost.Pointer Container provides containers for storing allocated heaps of objects in a safe manner and with minimal overhead. The purpose of the library, in particular, is to facilitate the programming of OO in C ++ by establishing a standard set of classes, methods and constructs for specific OO problems

With boost::ptr_vector instead of discarding reverse copies, you click on pointers to dynamically allocated objects. ptr_vector takes responsibility for these objects and ensures that they are deleted when ptr_vector itself is deleted. Clients that read with ptr_vector use the same interface as regular std::vector , so they don’t have to deal with pointers. For example, boost::ptr_vector<T>::front() returns a link.

The Motivation section of the documentation will help you decide if this is right for you.

+4
source

C ++ 11 has emplace_back , which perfectly conveys everything you pass it to the element constructor, and builds it directly in place :

 #include <vector> #include <iostream> struct X{ X(int i, float f, bool b){ std::cout << "X(" << i << ", " << f << ", " << b << ")\n"; } }; int main(){ std::vector<X> vx; vx.emplace_back(42, 3.14f, true); } 

Live example on Ideone.

In C ++ 03, you are out of luck and have to live with a copy of the ctor call (or rather, two with one parameter, one with a vector internal array). If your class is set up correctly, this should be just a minor inconvenience.

+3
source

The best way is to use elements by value in the containers of the standard library.
Standard library containers work on the semantics of values. ie: they store items at a cost, and you know for sure that the container accepts ownership of the items. Therefore, you do not need to explicitly manage memory manually.

As long as you obey Rule of Three , calling the copy constructor and destructor when storing items by value should not be a problem for you.

In the case of a pointer, as container elements, you must manually manage the memory and explicitly de-allocate the dynamic allocation.
In this case, when you need the object to be in dynamic memory, you should use Smart Pointers .
auto_ptr deprecated and cannot be used in the standard library containers because it has uninteresting destination behavior. unique_ptr is the best choice for auto_ptr proposed by the new C ++ 11 standard.

Please note that the smart pointer used depends on the lifetime and semantics of the property of the element, check the link to find out how to choose it for use.

+2
source

If you want to keep pointers, I like boost::ptr_vector

It acts like a vector, but retains and accepts pointer rights.

The advantage of boost::ptr_vector<X> over std::vector<some_smart_ptr<X>> is that access to the element on ptr_vector returns a reference to the object, not a reference to a (smart) pointer. This simplifies the use of the container with standard algorithms (since you do not need to bind a functor to dereference an element).

But if there is no good reason, it is better to save the object by value in a regular std::vector .

A good reason may include:

  • Very expensive to copy.
  • You cannot use perfect forwarding to create in-place.
  • A container must store polymorphic objects.
+1
source

It looks like you want to have one value that will have a life equivalent containing vector<T> . If so, then this is a good place to consider using std::shared_ptr<T> , which is the pointer number ref counted

 typedef std::shared_ptr<MyClass> MyClassPtr; ... vector<MyClassPtr> myVec; myVec.push_back(new MyClass(...)); 
0
source

Source: https://habr.com/ru/post/1401307/


All Articles