Я прочитал следующее: Размещение новых разрывов, констант и ссылок? и, прочитав слайды Маттиса Круза на C ++ Meeting, я запутался относительно следующего кода
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()
только разрушает объекты, а B.push_back({2})
использует размещение new для создания нового объекта в начале области памяти, выделенной B
.
- Я не совсем понимаю, почему доступ
B[0].i
является неопределенным поведением. - Мог ли компилятор кэшировать
B[0].i
и, возможно, вывести1
? - При чем здесь std :: launder? Действительно ли это инструмент, позволяющий убедиться, что такая оптимизация компилятора невозможна?
Стандартная реализация libcxx [llvm]:
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];
}
такое же, как на слайдах.
Ссылки с std 2017: