Я прочитал следующее: Размещение новых разрывов, констант и ссылок? и читая слайды от Маттис Крузе на C ++ Встрече Я запутался в отношении следующего кода
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})
использует размещение нового для создания нового объекта в начале ячейки памяти, выделенной 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:
- 8.3 (возможное нарушение)
- 8.4 (упоминание std :: launder)