Daniel Langr
Daniel Langr

Reputation: 23497

Elegant avoiding of value-initialization of vector elements in future C++?

When elements are default-inserted into an instance of std::vector<T>, they are value-initialized by default. I often work with multi-threaded high-performance codes, where such value-initialization might for large arrays represent an unacceptable sequential bottleneck.

The typical approach based on reserve() and push_back()/emplace_back() is of no use if in concurrent codes. I usually end up with one of the following options:

  1. definition of an empty default constructor for T,
  2. definition and usage of a custom allocator with empty construct() member function.

However, both solutions are far from being elegant and also have drawbacks. The former cannot be used for T being a POD type, such as double. The latter requires a given implementation of the C++ Standard Library to supoort the relatively new DefaultInsertable concept. Moreover, definition of a custom allocator is quite tedious.

Is there any chance that in the future of C++ there will be some straightforward way how to "turn off" this default-insertion/value-initialization?

UPDATE

Mayebe, I should've asked simply if it will be possible to avoid zero-initialization of default-inserted elements of a vector for arithmetic types.

Upvotes: 3

Views: 594

Answers (1)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275330

Vector is poorly suited to your needs. It supports resizing and accidental copy, neither of which make sense in a multi-threaded environment.

Write a simple container:

 template<class T,class Storage=std::aligned_storage_t<sizeof(T),alignof(T)>{
 struct buffer{
   static_assert(std::is_pod<T)::value, "pod only");
   std::size_t count;
   std::unique_ptr<Storage[]> storage;
 };

Populate it with container-esque begin/end/front/size/[]/empty etc.

Make it move only.

Use rule of zero (with =default).

Give it a explicit buffer(std::size_t) ctor that creates its content uninitialized.

Mix in some span/array_view types, and this should be suitable for your needs.

Maybe have emplace(size_t,Args&&) which does placement new for you with {}.

Upvotes: 3

Related Questions