C++11 introduces rvalue references and move semantics, which allow the new smart pointer type
std::unique_ptr
that can be used inside std::vector
. One might have some code like this:
std::vector<std::unique_ptr<Foo>> foos; ... foos.push_back(std::unique_ptr<Foo>(new Foo(...)));
This works just fine, but it's a bit convoluted. Since C++11 introduced both rvalue references and variadic templates,
std::vector
has a method emplace_back
, which looks more convenient. Let's use it:
std::vector<std::unique_ptr<Foo>> foos; ... foos.emplace_back(new Foo(...));
This works and looks good. However, there is a subtle problem: What happens if the new object of type
Foo
is constructed, but then the emplace_back
needs to allocate more memory, and that allocation fails?
The documentation that I can find states that nothing will happen in this case. Does "nothing" mean that we get a memory leak of one Foo object? Apparently it does - and at least a cursory look into the g++ 4.8 STL seems to confirm this suspicion. It appears that this is a potential memory leak that cannot really be avoided in good-looking code.
What to do about this? It would be nice if
emplace_back
guaranteed that the desired constructor is called no matter what happens. Unfortunately, such a guarantee would mean constructing the element explicitly in the cleanup path of a bad_alloc
exception, which is prone to triggering yet another exception. Seems like this is quite the conundrum...
hi
AntwortenLöschensomewhat late, but still
in good-looking code you have no new operators. use std::make_unique(...)
it is c++14, but trivial to implement(copy-paste)
std::vector can't take ownership of passed pointer because it assings no special meaning to raw pointers. boost::ptr_vector can