3
class C { ... };
std::vector<C> vc;
std::vector<C*> pvc;
std::vector<std::unique_ptr<C>> upvc;

Depending on the size of C, either the approach storing by value or the approach storing by pointer will be more efficient.

Is it possible to approximately know what this size is (on both a 32 and 64 bit platform)?

11
  • 6
    Efficient for what? It really depends on what you do with these vectors. If you're interested in performance, you'll have to measure it. Commented Mar 9, 2015 at 18:39
  • 1
    Probably also depends on what you are doing with your container. I would always store by value, not pointers until I can measure that this is bad. Never happened to me so far though. Commented Mar 9, 2015 at 18:41
  • 1
    Are you talking about memory overhead? Are you talking about the runtime cost of operations on a vector (e.g. - sorting)? What kind of efficiency are you trying to maximize? Commented Mar 9, 2015 at 18:42
  • 1
    making a template that either allocates a pointer in case of big object or not in case if object is small should solve this problem? Commented Mar 9, 2015 at 18:44
  • 1
    I can put a definite lower bound on that size. For a POD type, you should prefer a vector of that type at least until sizeof(POD) > sizeof(POD*). Less definitely, you should prefer a vector of that type at least until sizeof(POD) > 2 * sizeof(POD*) due to superior memory locality and lower memory usage (especially if you are dynamically allocating the objects at which to be pointed). Commented Mar 9, 2015 at 20:04

3 Answers 3

8

Yes, it is possible - benchmark it. Due to how CPU caches work these days, things are not simple anymore.

Check out this lecture about linked lists by Bjarne Stroustrup: https://www.youtube.com/watch?v=YQs6IC-vgmo

Here is an excelent lecture by Scott Meyers about CPU caches: https://www.youtube.com/watch?v=WDIkqP4JbkE

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

Comments

8

Let's look at the details of each example before drawing any conclusions.

Vector of Objects

A vector of Objects has first, initial performance hit. When an object is added to the vector, it makes a copy. The vector will also make copies when it needs to expand the reserved memory. Larger objects will take more time to copy, as well as complex or compound objects.

Accessing the objects is very efficient - only one dereference. If your vector can fit inside a processor's data cache, this will be very efficient.

Vector of Raw Pointers

This may have an initialization performance hit. If the objects are in dynamic memory, the memory must be initialized first (allocated).

Copying a pointer into a vector is not dependent on the object size. This may be a performance savings depending on the object size.

Accessing the objects takes a performance hit. There are 2 deferences before you get to the object. Most processors don't follow pointers when loading their data cache. This may be performance hit because the processor may have to reload the data cache when dereferencing the pointer to the object.

Vector of Smart Pointers

A little bit more costly in performance than a raw pointer. However, the items will automatically be deleted when the vector is destructed. The raw pointers must be deleted before the vector can be destructed; or a memory leak is created.

Summary

The safest version is to have copies in the vector, but has performance hits depending on the size of the object and the frequency of reallocating the reserved memory area. A vector of pointers takes performance hits because of the double dereferencing, but doesn't incur extra performance hits when copying because pointers are a consistent size. A vector of smart pointers may take additional performance hits compared to a vector of raw pointers.

The real truth can be found by profiling the code. The performance savings of one data structure versus another may disappear when waiting for I/O operations, such as networking or file I/O.

Operations with the data structures may need to be performed a huge amount of times in order for the savings to be significant. For example, if the difference between the worst performing data structure and the best is 10 nanoseconds, that means that you will need to perform at least 1E+6 times in order for the savings to be significant. If a second is significant, expect to access the data structures more times (1E+9).

I suggest picking one data structure and moving on. Your time developing the code is worth more than the time that the program runs. Safety and Robustness are also more important. An unsafe program will consume more of your time fixing issues than a safe and robust version.

2 Comments

I said "may", which means that you'll have to profile to find out. Depends on the implementation of unique pointer. There are other smart pointers than unique_ptr. You could also look at the assembly language listing generated by the compiler.
No, unique_ptr will not be any slower than raw pointer with manual memory management.
-1

For a Plain Old Data (POD) type, a vector of that type is always more efficient than a vector of pointers to that type at least until sizeof(POD) > sizeof(POD*).

Almost always, the same is true for a POD type at least until sizeof(POD) > 2 * sizeof(POD*) due to superior memory locality and lower total memory usage compared to when you are dynamically allocating the objects at which to be pointed.

This kind of analysis will hold true up until sizeof(POD) crosses some threshold for your architecture, compiler and usage that you would need to discover experimentally through benchmarking. The above only puts lower bounds on that size for POD types.

It is difficult to say anything definitive about all non-POD types as their operations (e.g. - default constructor, copy constructors, assignment, etc.) can be as inexpensive as a POD's or arbitrarily more expensive.

Comments

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.