I have read the following: Placement new breaks consts and references? and by reading the slides from Matthis Kruse at the C++ Meeting I am confused regarding the following code
struct U { const int i; };
std::vector<U> B;
B.push_back({ 1 });
B.clear();
B.push_back({ 2 });
const int v = B[0].i; // <- Undefined Behavior
B.clear()
only destructs the objects, and B.push_back({2})
uses placement new to construct a new object at the start of the memory location B
has allocated.
- I don't understand quite why the access
B[0].i
is undefined behavior. - Could the compiler have cached
B[0].i
and possibly output1
? - What has std::launder to do with all this? Is it a tool to really make sure these kind of compiler optimizations cannot happen?
The standard libcxx [llvm] implementation:
template <class Tp, class Allocator>
inline typename vector<Tp, Allocator>::reference
vector<Tp, Allocator>::operator[](size_type n)
{
assert(n < size(), "vector[] index out of bounds");
return this->__begin_[n];
}
is the same as in the slides.
References from std 2017: