In their example of std::uninitialized_default_construct:
struct S { std::string m{ "Default value" }; };
constexpr int n {3};
alignas(alignof(S)) unsigned char mem[n * sizeof(S)];
try
{
auto first {reinterpret_cast<S*>(mem)};
auto last {first + n}; // (1)**********
std::uninitialized_default_construct(first, last);
// (2)**********
for (auto it {first}; it != last; ++it) {
std::cout << it->m << '\n';
}
std::destroy(first, last);
}
catch(...)
{
std::cout << "Exception!\n";
}
// Notice that for "trivial types" the uninitialized_default_construct
// generally does not zero-fill the given uninitialized memory area.
int v[] { 1, 2, 3, 4 };
const int original[] { 1, 2, 3, 4 };
std::uninitialized_default_construct(std::begin(v), std::end(v));
// (3)**********
// for (const int i : v) { std::cout << i << ' '; }
// Maybe undefined behavior, pending CWG 1997.
I have three questions. (Mark as ********** )
- Since
Sandunsigned chararen't pointer-interconvertible, willlastpoint to past-the-end ofmem? Is pointer arithmetic undefined behavior here? - Is std::launder needed here to make
firstandlastactually point toS? e.g.first = std::launder(first); last = first + n; - Is it really undefined behavior to print elements of
v? CWG 1997 talk aboutunsigned char[]storage, but the above example has initializedvwithints.