Consider the following code:
#include <memory>
template<typename Allocator>
char* allocate_array(Allocator alloc, size_t n)
{
static_assert(std::is_same<typename Allocator::value_type, char>::value);
char* data = alloc.allocate(n);
// (1)
for (size_t i=0; i<n; ++i) {
new (data+i) char();
}
return data;
}
char* copy_array(size_t n, const char* original)
{
char* copy = allocate_array(std::allocator<char>(), n);
// (2)
for (size_t i=0; i<n; ++i) {
copy[i] = original[i];
}
return copy;
}
Is the placement-new initialization marked by (1) necessary to prevent the program from having undefined behaviour, even if every char is guaranteed to be written to in (2) before it can be read? Or can it be safely removed?
Note that this is not being optimized away, even at -O3 I see both gcc and clang generating subsequent calls to both memset() and memcpy().
Is the placement-new initialization marked by (1) necessary to prevent the program from having undefined behaviour.
Technically yes, as far as I can tell.
[basic.life]
The lifetime of an object of type T begins when:
- storage with the proper alignment and size for type T is obtained, and
- its initialization (if any) is complete (including vacuous initialization) ([dcl.init]),
... before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any glvalue that refers to the original object may be used but only in limited ways. ... The program has undefined behavior if:
- the glvalue is used to access the object, or
- ...
Note that this is not being optimized away
Instead of value initialising the chars, you could default initialise. Then their value would be left indeterminate until the assignment, and thus there should be no need for memset. Also, there is a standard function for this, so there is no need to write the loop:
std::uninitialized_default_construct(data, data + n);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With