Creating std::vector of nonmovable type

泪湿孤枕 提交于 2019-12-08 07:17:31

问题


I have a std::vector named args (I don’t know the size of the vector at compile time) and a non movable type NonMoveable.

I want to create a vector of the same size as args, so that it equals to {NonMovable(args[0], additional_arg), NonMovable(args[1], additional_arg), …, NonMovable(args.back(), additional_arg)}

I don’t need to change the size of the vector later. How do I do that?

I can’t reserve() then emplace_back() because emplace_back() requires moving (to allow reallocation which is not possible in my case)

I do not want to use std::list because it is not contiguous.


回答1:


You can:

  • Have a vector<unique_ptr<T>> or vector<optional<T>> or vector<some_other_defer_storage_mechanism<T>> instead of just vector<T> - these are all wrapper types that adding some functionality T without affecting T (unique_ptr<T> makes it movable, optional<T> ensures default construction so you can construct with the right size then emplace() within the optional, etc.)
  • Use deque<T> which does not require movability for emplace_back (although you lose Contiguity)
  • Write your own dynamic array that is roughly equivalent to a pair<unique_ptr<T[]>, size_t> that just allocates space for n Ts and then placement-news onto each of them, ensuring that destruction does the right thing. This isn't so bad to implement - since you won't be changing the size, you need to support a very minimal amount of overall operations.

Whichever one of these is the best answer really depends.




回答2:


If you want the elements to be contiguous, you could use the good old 2 times dynamic array construction:

// allocate a dynamic array
NonMoveable *mv = std::allocator<NonMoveable>().allocate(args.size());

// use inplace new to construct the NonMoveable elements
for (unsigned int i = 0; i < args.size(); i++) {
    new(mv + i) NonMoveable(args[i], additional_arg);
}

...  // use the dynamic array

// Explicitely delete the elements
for (unsigned int i = 0; i < args.size(); i++) {
    mv[i].~NonMoveable();
}

// and de-allocate
std::allocator<NonMoveable>().deallocate(mv, args.size());

It is rather C-ish but meets the contiguous requirement. Of course this should be encapsulated in a custom container to allow automatic destruction and de-allocation at container destruction.



来源:https://stackoverflow.com/questions/54953039/creating-stdvector-of-nonmovable-type

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!