4

How can I decide when choosing between std::containers (std::vector or std::array) and smart pointers pointing to arrays

I know containers are objects for memory managment. They are exception safe and there will not be any memory leak and they also provide veriuty of functions for memory managment(push.back etc) and smart pointers are pointer that also do not leak memory because they delete themsefs when they are not needed anymore(like unique_ptr when geting out of scope). Propably in containers there is an overhead every time they are created.

My question is how can i decide which method to use and why.

std::vector <unsigned char>myArray(3 * outputImageHight * outputImageWidth);

std::unique_ptr<unsigned char[]>myArray(new unsigned char[3 * outputImageHight * outputImageWidth]);
8
  • 4
    Always default to a container, in 99.99% of all cases it will be correct. Commented Feb 15, 2019 at 11:23
  • 1
    Except if you measure a drop in performance because you have something that would not be there in the raw unique_ptr. That would be the 0.01%. Commented Feb 15, 2019 at 11:25
  • 1
    Please replace the picture with the text instead. Commented Feb 15, 2019 at 11:25
  • 1
    @MatthieuBrucher And that performance-drop is a measured top-three bottleneck of the program. Commented Feb 15, 2019 at 11:29
  • So smart pointers for arrays exists only for 0.01% of the cases Commented Feb 15, 2019 at 11:30

3 Answers 3

6

I would use the vector. Your pointer version offers basically no improvements over the vector, and you lose a lot of useful functionality. You're most likely going to need to measure the size and iterate your array at some point, with a vector you get this for free, whereas you'd need to implement it yourself for your pointer version; at which point you may as well have just used the vector to begin with.

There may be a performance cost instantiating the vector, but I doubt that it would be a bottleneck for most applications. If you're creating so many vectors that instantiating them is costing you time, you can probably be smarter about managing them (pooling your memory, custom vector allocators, etc). If in doubt, measure.

One example where you might need to use the unique_ptr<> version might be if you're working with a library written in C where you lose ownership of the array. For example:

std::unique_ptr<unsigned char[]>myArray(
    new unsigned char[3 * outputImageHight * outputImageWidth]);

my_c_lib_data_t cLibData;
int result = my_c_lib_set_image(cLibData, myArray);

if (MYLIB_SUCCESS == result)
    // mylib successfully took ownership of the char array, so release the pointer.
    myArray.release();

If you have the choice though, prefer to use C++ style containers where you can.

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

2 Comments

Actually i do need to iterate at the array and i actually do need to measure the size and actually implement it myself. And i also thought about this but my question is that if there is never a reason to use smart pointers for arrays why they even add them?
@Aris - Good question! I added an extra paragraph to my answer that covers an example where the unique_ptr version might be useful.
4

std::vector, primarily because it better represents the "sequence of items in contiguous memory", it is the default representation for that, and enables a wide range of common operations.

vector has move semantics, so the benefit of std::unique_ptr is limited.

If you are lucky, your STL implementation `provides small vector optimization, skipping the memory allocation for small sizes.
-- edit: I wasn't aware SBO is apparently prohibited by the standard - sorry for getting your hopes up, thanks @KarlNicholl

If pointer semantics are required, a unique_ptr<vector<T>> or shared_ptr<vector<T>> is a valid choice with little overhead.

boost did introduce shared_array etc., that represent your second option better, but I haven't seen them get much traction.

1 Comment

Is small vector optimization supported in std::vector nowadays? Last I knew it was not permitted because swap() would potentially invalidate iterators with an SBO vector implementation, which is not allowed (see here stackoverflow.com/a/8191356/52724). That said, boost::container::small_vector exists and is useful for small-buffer optimization.
0

Always use STL containers except in situation where you have good reason to use pointers. Reasons are reliability and readability, IMO.

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.