<div dir="auto"><div><br><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, 10 Nov 2024, 10:06 André Offringa via Std-Proposals, &lt;<a href="mailto:std-proposals@lists.isocpp.org">std-proposals@lists.isocpp.org</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Dear all,<br>
<br>
I&#39;d like to float the idea to make it possible to construct a <br>
std::complex and a std::vector uninitialized. Basically, I would propose <br>
something like the following to exist.<br>
<br>
A tag structure:<br>
<br>
struct skip_initialization_t {};<br>
constexpr skip_initialization_t skip_initialization;<br>
<br>
And the constructor overloads for std::vector and std::complex that have <br>
this tag as parameter, that do not initialize their data values.<br>
<br>
For vector, the overload:<br>
<br>
// Construct a vector with n elements without initializing them<br>
vector(size_t n, skip_initialization_t, const allocator_type&amp; allocator <br>
= Alloc())<br>
<br>
...and optionally &quot;for consistency&quot; but less often used:<br>
<br>
// Set the size of the vector to n elements; new elements are left <br>
uninitialized<br>
void resize(size_t n, skip_initialization_t)<br>
<br>
// Add n uninitialized values at the given position<br>
// (maybe too obscure...)<br>
iterator insert(const_iterator position, size_t n, skip_initialization_t)<br>
<br>
For complex, the overload:<br>
<br>
// Leave real and imaginary values uninitialized<br>
constexpr complex(skip_initialization_t)<br>
<br>
Some motivation:<br>
<br>
My background is that I am involved in the development of scientific <br>
numerical software for radio telescopes, which deal with petabytes of <br>
data, often complex valued ones. We regularly come across situations <br>
where we need to allocate some data and fill it only later. If we use <br>
std::vector for this, say for double values, the data is first <br>
zero-initialized. While on the full scale of things this is &quot;a few <br>
percent&quot; level cost, given our data sizes and the amount of compute we <br>
do, this is not insignificant. We benchmark a lot so we have a <br>
reasonable idea of its cost. While it&#39;s maybe a bit niche, there are <br>
multiple stack-overflow-like questions of people that ask how to do this <br>
-- and I&#39;m sure that if it would be available it would see more use.<br>
<br>
A very common use-case where initialization can be skipped to save <br>
performance (which is not limited to our domain) is this:<br>
<br>
std::ifstream file(&quot;myfile.bin&quot;);<br>
std::vector&lt;char&gt; buffer(buffer_size);<br>
file.read(&amp;buffer[0], buffer_size);<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">This is exactly the use case that string::resize_for_overwrite solves. I think there is already a proposal to add a similar function to vector. </div><div dir="auto"><br></div><div dir="auto">The committee has seen lots of proposals for a tag that says to leave a container uninitialised, and has always decided we don&#39;t want that because it&#39;s too error-prone and risky.</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
My proposal is thus that the second line can become:<br>
<br>
std::vector&lt;char&gt; buffer(buffer_size, std::skip_initialization);<br>
<br>
Currently, to get around the issue, we wrote our own vector (UVector) <br>
class that skips initialization. It has the exact same interface as <br>
std::vector, except unless values are explicitly specified they leave <br>
the data array uninitialized. We still prefer to use std::vector, and <br>
only use UVector when we explicitly need that functionality, for one <br>
because using UVector is obviously less safe, and second we sometimes <br>
need compatibility with std::vector for external libraries. This is thus <br>
rather awkward, and a std::vector constructor that would skip <br>
initialization would be a small fix that solves the issue. Moreover, I <br>
think using a tagged constructor makes it explicit that the user wanted <br>
this unsafe behaviour, at the place it is constructed, instead of at the <br>
place where the vector is declared (as is now the case for us with UVector).<br>
<br>
For std::complex, it&#39;s even more fundamental as there&#39;s basically no <br>
good work-around to skip initialization. We&#39;ve used approaches where we <br>
first allocated an uninitialised double array and casted it to a <br>
std::complex array, but this causes undefined behaviour because of type <br>
punning rules (complex is special in that casting a complex&lt;double&gt; to a <br>
double[2] is allowed, but the other way around is not allowed). It works <br>
in most situations, but we&#39;ve also seen compilers (gcc in this case) <br>
make (correct) optimizations that cause this to break, a situation like:<br>
<br>
double a[2];<br>
std::complex&lt;double&gt;* b = reinterpret_cast&lt;std::complex&lt;double&gt;*&gt;(a);<br>
*b = &lt;some value&gt;<br>
<br>
sometimes causes b to stay uninitialized even after the assignment, <br>
because the compiler apparently deduces undefined behaviour (pretty <br>
fancy behaviour of the compiler! -- but makes it impossible to get the <br>
intended behaviour). As a result there are cases where we don&#39;t use <br>
complex values at all, and keep everything as double, resulting in much <br>
more verbose code if we need to do operations on it (+, -, *, /, abs, <br>
norm, exp, etc.). I&#39;ve also written my own complex class at some point, <br>
but using two complex classes is quite messy.<br>
<br>
The two proposed constructors would make our live a lot easier. There <br>
are probably other std data types that, theoretically, could use <br>
skip_initialization construction, but the two I listed here are I think <br>
by far the most important once -- I don&#39;t think I&#39;ve seen any need for <br>
more. I&#39;m curious to what people think.<br>
<br>
Kind regards,<br>
André Offringa<br>
-- <br>
Std-Proposals mailing list<br>
<a href="mailto:Std-Proposals@lists.isocpp.org" target="_blank" rel="noreferrer">Std-Proposals@lists.isocpp.org</a><br>
<a href="https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals" rel="noreferrer noreferrer" target="_blank">https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals</a><br>
</blockquote></div></div></div>

