3

Adding objects to vectors vs adding pointers to vectors in c++.

Example:

std::vector<Size> buildings;
Size building(buildingWidth, buildingHeight);
buildings.push_back(building);

VS

std::vector<Size*> buildings;
Size *building = new Size(buildingWidth, buildingHeight);
buildings.push_back(building);

Which one is better in terms of memory/performance?

The first one basically creates an object on the stack and adds it to a vector. So there is one instantiation followed by one copy into the vector.

The second one creates an object on the heap. There is one instantiation, but there is no copy into the vector.

Am I correct?

1
  • 1
    It's correct, but in the second case you have to explicitly delete all the stored objects before the vector is destroyed. Commented May 29, 2013 at 15:00

6 Answers 6

4

The two storage techniques serve different purposes.

The first technique is useful with "homogenous" vectors, where you do not need polymorphic behavior, and object slicing is not an issue. You get automated resource management in return: you do not need to worry about the ownership of your objects, because the vector makes a copy. A copy is also made internally every time your vector is resized. This consideration makes the first option less attractive when copying the object is somewhat expensive; you need to profile your code to see if this consideration applies to it.

The second technique puts the responsibility for managing the memory on you: every time you decide to remove an object from your vector of pointers, you need to take the ownership, and eventually delete the object explicitly. You can use smart pointers to address the resource management issue. This technique lets you avoid copying, but the process of accessing elements inside the container becomes slightly more involved.

Sign up to request clarification or add additional context in comments.

1 Comment

A way to mitigate some of the drawbacks of the second option is to store smart pointers instead of plain pointers.
0

They both usually have relatively similar performance, depending on the object size and copy semantics of the object. With regards to memory leaks and usability, the first way is usually much better.

7 Comments

Uhm, if the copy constructor of Size were expensive they would not have similar performance at all.
@MatteoItalia, in this case using a move constructor can be a solution.
@soon: Indeed. Or just emplace.
Also, since the original question gave a specific object, Size, that maps to 2 number elements, it's unlikely to be very heavy.
Yes, copying is simple in my case. I guess then the first option is better.
|
0

It really depends on the nature of Size. If the object is big (insofar that the copy constructor has to do a lot of work), then you could consider your pointer idea. However you will have to control the memory yourself and, whatever you do, don't inherit from std::vector as inheriting from the standard containers is not a good idea (for one thing they don't have virtual destructors)!

You could build some copy on write semantics in your Size class (a bit like implementations of std::string).

Or have a default constructor and a swap method for Size (you'll need the default constructor to be used in std::vector anyway). Use the swap method to swap in a new Size object into the position in the vector.

On the basis that "premature optimisation is the root of all evil" (attrib. Tony Hoare), I'd stick with the simplest approach; namely your first idea and see how that goes.

3 Comments

I find your comment about not inheriting from std containers because of lack of virtual destructors, unconvincing. The absence of virtual destructors limits the design of your inheriting class (for good reasons) but does not exclude inheritance.
There are indeed many more reasons - see other SO questions - but I thought I should cite at least one of them.
Thanks for the link. The accepted answer (A good answer IMO) says it is fine, as long as you are clear on the public std::vector base. Any coder should be familiar with the design of the std:: containers, i.e. they are not of OO design. And as such would not do stupid things with a vector base.
0

It really comes down to

  • What operations are going to be performed on that vector
  • How frequently objects will be pushed onto the vector

If you're going to be doing any kind of mutable operation on the vector, then you'd better go with a shared_ptr type.

Ultimately, with any kind of performance-related question, it's best to test it out yourself under the conditions of your application.

Comments

0

Why not do this:

std::vector<Size> buildings;
buildings.resize(1);
buildings[0].setSize(buildingWidth, buildingHeight);

This way the constructor is only called once, and you don't have to manage the memory yourself. The only disadvantage I can think of is that the width and height are set twice (once in constructor, once in "setSize"), but I don't think you can get away from that unless you use the std::vector<Size *> approach.

4 Comments

Or, if you're using c++11, emplace_back.
Ooh, I didn't know about emplace_back. C++11 gets more appealing to me every day.
Yup. Even more porting problems to contend with :-(
You have to come to C++11 land soon! It is like Disneyland.
-1

I think the second approach of using vector of pointers is a better of the two options. Because of two simple reasons

  1. If the objects size are bigger then using vector of objects will add unnecessary copying.
  2. If you are passing the vector of objects as argument to a method and then try to modify any object in the vector then it will not get reflected at all the places.

2 Comments

@DavidO I didn't get anything from your comment.
when you say "better of the two options", you are not acknowledging those reasons that might make the first option better. There are rarely "absolutes". The first option is better for trivial (to construct) objects, and doesn't require any thought for RAII. The second solution requires that thought be given to RAII, and adds a level of indirection, which both contribute to code complexity. There are pros and cons that have to be weighed. "Better" can only be "Better in a given situation".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.