Is there any use for unique_ptr with array?

2019-01-02 19:53发布

std::unique_ptr has support for arrays, for instance:

std::unique_ptr<int[]> p(new int[10]);

but is it needed? probably it is more convenient to use std::vector or std::array.

Do you find any use for that construct?

16条回答
流年柔荑漫光年
2楼-- · 2019-01-02 20:05

An std::vector can be copied around, while unique_ptr<int[]> allows expressing unique ownership of the array. std::array, on the other hand, requires the size to be determined at compile-time, which may be impossible in some situations.

查看更多
初与友歌
3楼-- · 2019-01-02 20:05

Contrary to std::vector and std::array, std::unique_ptr can own a NULL pointer.
This comes in handy when working with C APIs that expect either an array or NULL:

void legacy_func(const int *array_or_null);

void some_func() {    
    std::unique_ptr<int[]> ptr;
    if (some_condition) {
        ptr.reset(new int[10]);
    }

    legacy_func(ptr.get());
}
查看更多
初与友歌
4楼-- · 2019-01-02 20:08

There are tradeoffs, and you pick the solution which matches what you want. Off the top of my head:

Initial size

  • vector and unique_ptr<T[]> allow the size to be specified at run-time
  • array only allows the size to be specified at compile time

Resizing

  • array and unique_ptr<T[]> do not allow resizing
  • vector does

Storage

  • vector and unique_ptr<T[]> store the data outside the object (typically on the heap)
  • array stores the data directly in the object

Copying

  • array and vector allow copying
  • unique_ptr<T[]> does not allow copying

Swap/move

  • vector and unique_ptr<T[]> have O(1) time swap and move operations
  • array has O(n) time swap and move operations, where n is the number of elements in the array

Pointer/reference/iterator invalidation

  • array ensures pointers, references and iterators will never be invalidated while the object is live, even on swap()
  • unique_ptr<T[]> has no iterators; pointers and references are only invalidated by swap() while the object is live. (After swapping, pointers point into to the array that you swapped with, so they're still "valid" in that sense.)
  • vector may invalidate pointers, references and iterators on any reallocation (and provides some guarantees that reallocation can only happen on certain operations).

Compatibility with concepts and algorithms

  • array and vector are both Containers
  • unique_ptr<T[]> is not a Container

I do have to admit, this looks like an opportunity for some refactoring with policy-based design.

查看更多
看淡一切
5楼-- · 2019-01-02 20:11

In a nutshell: it's by far the most memory-efficient.

A std::string comes with a pointer, a length, and a "short-string-optimization" buffer. But my situation is I need to store a string that is almost always empty, in a structure that I have hundreds of thousands of. In C, I would just use char *, and it would be null most of the time. Which works for C++, too, except that a char * has no destructor, and doesn't know to delete itself. By contrast, a std::unique_ptr<char[]> will delete itself when it goes out of scope. An empty std::string takes up 32 bytes, but an empty std::unique_ptr<char[]> takes up 8 bytes, that is, exactly the size of its pointer.

The biggest downside is, every time I want to know the length of the string, I have to call strlen on it.

查看更多
查无此人
6楼-- · 2019-01-02 20:14

Some people do not have the luxury of using std::vector, even with allocators. Some people need a dynamically sized array, so std::array is out. And some people get their arrays from other code that is known to return an array; and that code isn't going to be rewritten to return a vector or something.

By allowing unique_ptr<T[]>, you service those needs.

In short, you use unique_ptr<T[]> when you need to. When the alternatives simply aren't going to work for you. It's a tool of last resort.

查看更多
其实,你不懂
7楼-- · 2019-01-02 20:18

Scott Meyers has this to say in Effective Modern C++

The existence of std::unique_ptr for arrays should be of only intellectual interest to you, because std::array, std::vector, std::string are virtually always better data structure choices than raw arrays. About the only situation I can conceive of when a std::unique_ptr<T[]> would make sense would be when you're using a C-like API that returns a raw pointer to a heap array that you assume ownership of.

I think that Charles Salvia's answer is relevant though: that std::unique_ptr<T[]> is the only way to initialise an empty array whose size is not known at compile time. What would Scott Meyers have to say about this motivation for using std::unique_ptr<T[]>?

查看更多
登录 后发表回答