Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Element Lifetime of STL Containers

I'm trying to save objects in an stl container (in this case a vector) and want the container to destroy the objects at its destruction, but I can't quite figure out the details.

One way I don't want to do it is simply using it like

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

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

The most direct alternative is to use pointers to store dynamically allocated objects, but then the destructor of MyClass won't be called at vector destruction. Storing auto_ptr instead of normal pointers gives an error at myVec.push_back(...).

Is there anyway to avoid the first option while having the container's destructor call the elements' destructor?

Thank you for your answers!

EDIT

Consider the similar problem; how to implement a container owning objects using an abstract base class. Unique pointer (Boost's unique_ptr) don't have copy constructors so one can't use that 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.
like image 753
Jens Åkerblom Avatar asked Dec 28 '22 04:12

Jens Åkerblom


2 Answers

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

Boost.Pointer Container provides containers for holding heap-allocated objects in an exception-safe manner and with minimal overhead. The aim of the library is in particular to make OO programming easier in C++ by establishing a standard set of classes, methods and designs for dealing with OO specific problems

With a boost::ptr_vector, instead of pushing back copies, you push pointers to dynamically allocated objects. The ptr_vector takes ownership of these objects and ensures that they are deleted when the ptr_vector itself is deleted. Clients that read from the ptr_vector use the same interface as a regular std::vector, so they don't have to deal with pointers. For example, boost::ptr_vector<T>::front() returns a reference.

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

like image 174
Emile Cormier Avatar answered Jan 09 '23 00:01

Emile Cormier


C++11 has emplace_back which will perfectly forward whatever you give it to the elements constructor and construct 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're out of luck and have to live with the copy ctor call (or rather, two - one in the parameter, one into the vector's internal array). If your class is desgined correctly, it should only be a minor efficiency inconvenience.

like image 35
Xeo Avatar answered Jan 08 '23 23:01

Xeo