15

Please consider this code:

class A
{

};

int main()
{
    std::vector<A> test;
    test.push_back(A());
}

The constructor and destructor will be called twice, also memory will be allocated twice and the object will copied, now not only is that potentially bad for performance it could also lead to run time errors, especially if there's some cleanup going on in the destructor. The way i'd usually get around this is to just create a vector of pointers instead :

std::vector<A*> test;
test.push_back(new A());

My question is two fold, is this common practice and is it good practice? Or is there a better way? If this turns out to be a dupe please let me know and i'll close the question, but I couldn't find anything on searching.

Geoff
  • 457
  • 3
  • 9
  • 7
    It is common practice to *not* use pointers. And *not* using pointers is good practice. And it would be better practice if you didn't use pointers and implement a *movement* constructor. – Some programmer dude Oct 29 '16 at 21:14
  • still, `std::vector test` is necessary when polymorphism is required on the list (and B is the base class). But only here... and I agree that's bad for memory leaks/double frees. – Jean-François Fabre Oct 29 '16 at 21:14
  • The better way is to implement a move constructor for `B`. – Ryan Bemrose Oct 29 '16 at 21:16
  • 4
    @Jean-FrançoisFabre Wouldn't a smart pointer still be more appropriate in that case? At least as long as the vector is supposed to own the objects. – Dan Mašek Oct 29 '16 at 21:16
  • @Jean-FrançoisFabre That's a typo; my bad, but thanks for the info :) – Geoff Oct 29 '16 at 21:16
  • @DanMašek probably. I'm still stuck in 2005 when it comes to C++. My C++ needs dusting. I'm still in the phase where I'm learning from answers. – Jean-François Fabre Oct 29 '16 at 21:18
  • These micro-optimizations often don't give you benefits that are worth the effort it takes to implement them. – Dietrich Epp Oct 29 '16 at 21:19
  • @DietrichEpp right, better make it work _then_ optimize. But the good answer below doesn't take that much effort and saves time if the object is big (example: vector of vectors of fixed length). – Jean-François Fabre Oct 29 '16 at 21:20
  • 3
    It is not a micro-optimization, and `emplace_back` makes the optimization very trivial. – asu Oct 29 '16 at 21:21
  • I remember seeing this method a long time ago, but never bothered to use it. That's really good (see your score on that one!) – Jean-François Fabre Oct 29 '16 at 21:23
  • @Asu: Yes, the difference between `emplace_back()` and `push_back()` with an rvalue is often going to be a micro-optimization. – Dietrich Epp Oct 29 '16 at 21:24
  • if you write `emplace_back(A{});` then in C++11 the results are identical. If you write `emplace_back();` you will avoid a useless allocation, construction, destruction, ~~copy~~ move (in c++11) and deallocation (even if automatic allocation is very cheap and is greatly optimizable) – asu Oct 29 '16 at 21:26

1 Answers1

25

Use emplace_back.

std::vector<A> test;
test.emplace_back();
//test.emplace_back(constructor, parameters);

This way, A will be constructed in-place, so no copy or move will occur.

Edit: To clarify on the comments on the question - No, this will not change from push_back if you pass it a temporary. For instance,

test.emplace_back(A{});

Will, in C++11, cause a temporary A to be constructed, moved and destroyed, as if you used push_back.

asu
  • 1,875
  • 17
  • 27