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]);
Aris
  • 138
  • 1
  • 12

3 Answers3

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.

Karl Nicoll
  • 16,090
  • 3
  • 51
  • 65
  • 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 Feb 15 '19 at 11:43
  • 1
    @Aris - Good question! I added an extra paragraph to my answer that covers an example where the `unique_ptr` version might be useful. – Karl Nicoll Feb 15 '19 at 11:52
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.

peterchen
  • 40,917
  • 20
  • 104
  • 186
  • 2
    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 https://stackoverflow.com/a/8191356/52724). That said, [`boost::container::small_vector`](https://www.boost.org/doc/libs/1_69_0/doc/html/boost/container/small_vector.html) exists and is useful for small-buffer optimization. – Karl Nicoll Feb 15 '19 at 12:00
0

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

risbo
  • 188
  • 7