Unique_ptr <int []> or vector <int>?

If you do not need dynamic growth and you do not know the size of the buffer at compile time, when unique_ptr<int[]> should be used instead of vector<int> ?

Is there a significant performance loss when using vector instead of unique_ptr ?

+8
source share
5 answers

When using std::vector vs. std::unique_ptr<int[]> there is no performance loss. The alternatives are not entirely equivalent, because since the vector can be grown, but the pointer cannot (can this be either an advantage or a disadvantage, did the vector make a mistake?)

There are other differences, such as the fact that the values ​​will be initialized in std::vector , but they will not be if you are a new array (unless you use initialization initialization ...).

At the end of the day, I personally chose std::vector<> , but I'm still C ++ 03 code without std::unique_ptr .

+4
source

If you are in a position where vector<int> is even an opportunity, you probably want to go for it, except in extreme and rare circumstances. And even in this case, the best answer might be a non-standard type instead of unique_ptr<int[]> .

So what is unique_ptr<int[]> good for unique_ptr<int[]>

unique_ptr<T[]> really shines in two circumstances:

1. You need to process the malloc / free resource from some inherited function, and you would like to do it in a modern safe style:

 void foo() { std::unique_ptr<char[], void(*)(void*)> p(strdup("some text"), std::free); for (unsigned i = 0; p[i]; ++i) std::cout << p[i]; std::cout << '\n'; } 

2. You need to temporarily protect the new resource [] before transferring it to another owner:

 class X { int* data_; std::string name_; static void validate(const std::string& nm); public: ~X() {delete [] data_;} X(int* data, const std::string& name_of_data) : data_(nullptr), name_() { std::unique_ptr<int[]> hold(data); // noexcept name_ = name_of_data; // might throw validate(name_); // might throw data_ = hold.release(); // noexcept } }; 

In the above scenario, X owns the pointer passed to it, whether the constructor is successful or not. This specific example assumes the noexcept default constructor for std::string , which is optional. But:

  • This point is generalized to circumstances not related to std::string .
  • A std::string is the default constructor that throws lame.
+6
source

C ++ 14 introduces std :: dynarray for this purpose.

Now between these two constructs:

  • auto buffer = std::make_unique<int[]>( someCount );
  • auto buffer = std::vector<int>( someCount, someValue );

The first gives you an uninitialized int array, and the second initializes it with a value (0, if not provided). Therefore, if you do not need memory initialization, because you somehow rewrite it with something more complicated than std::fill , select 1, if not, select 2.

+4
source

std::vector stores the length of both the size of the variable and the size of the selected data, along with a pointer to the data that it itself. std::unique_ptr just saves a pointer, so there may be a slight gain when using std::unique_ptr .

No one has mentioned that a vector provides iterators and functions such as size() , where there is no unique ptr. Therefore, if you need iterators, use std::vector

+3
source

The objective part:

No, probably, there should not be a significant difference in performance between the two (although I believe that it depends on the implementation, and you should measure its criticality).

The subjective part:

std::vector will give you a well-known interface with .size() and .at() and iterators that will play well with all kinds of other code. Using std::unique_ptr gives you a more primitive interface and allows you to track details (e.g. size) separately. Therefore, by prohibiting other restrictions, I would prefer std::vector .

+1
source

Source: https://habr.com/ru/post/952610/


All Articles