C++ Logo

std-proposals

Advanced search

Add vector/string resize functions that don't initialize any new storage

From: Nathan James <n.james93_at_[hidden]>
Date: Wed, 23 Dec 2020 11:04:36 +0000
In P1020R1 and subsequently adjusted in P1973R1, we were granted the
ability to create smart pointers that don't perform initialization on
types that are trivially default construbible. This results in slightly
better performance if you plan to initialize the storage afterwards.

It would be nice if this behaviour could be extended to vector and
basic_string. Following the convention used in P1973R1, I'd suggest:

> void vector::resize_for_overwrite(size_type count);
> void basic_string::resize_for_overwrite(size_type count);

I've also toyed with the idea of a tag type, which could also be used
for construction as well.
> struct default_init{};
>
> explicit vector(size_type count,
> default_init tag,
> const Allocator& alloc = Al locator());
> explicit basic_string(size_type count,
> default_init tag,
> const Allocator& alloc = Al locator());
> void vector::resize(size_type count, default_init tag);
> void basic_string::resize(size_type count, default_init tag);

Using the tag has the benefit that the constructor signature is similar
to the constructor that takes a value for the 2nd parameter, enabling
simpler migration for any codebases which wish to take advantage of
this.

> #if __has_feature(CXX2B_DEFAULT_INIT_RESIZE)
> #define DEFAULT_INIT std::default_init{}
> #else
> // Use brace initialization to default init a value.
> #define DEFAULT_INIT {}
> #endif
>
> std::string Buffer(RequiredSize, DEFAULT_INIT);

The motivation for this is sometimes it's nice to use basic_string and
vector as a buffer, particularily when interacting with c apis that
accept a buffer and a length, then fill that container themselves. A
common example of this would be snprintf. Currently, to snprintf on a
std::string, its first required to resize the string, which will zero
out all the storage of the string. However as we know we are going to
overwrite the storage in the call to snprintf this is a redundant
operation.

I'd imagine implementing this is just as simple as using `new (Storage)
T`, analogous to P1020R1.

Thanks for reading,
Nathan James

Received on 2020-12-23 05:04:41