Рассмотрим следующую, упрощенную и неполную реализацию вектора фиксированного размера:
template<typename T>
class Vec {
T *start, *end;
public:
T& operator[](ssize_t idx) { return start[idx]; }
void pop() {
end--;
end->~T();
}
template<typename... U>
void push(U... args) {
new (end) T { std::forward<U>(args)... };
end++;
}
};
Теперь рассмотрим следующее T:
struct T {
const int i;
};
И следующий прецедент:
Vec<T> v;
v.push(1);
std::cout << v[0].i;
v.pop();
v.push(2);
std::cout << v[0].i;
Оператор индекса использует указатель start
для доступа к объекту. Объект в этой точке был уничтожен pop
, а другой объект был создан в своем хранилище на push(2)
. Если я правильно прочитал документацию, относящуюся к std:: washder, это означает, что поведение v[0]
в строке ниже undefined.
Как предполагается, что std:: frod используется для исправления этого кода? Нужно ли начинать и заканчивать отмывание каждый раз, когда используется новое место? Текущие реализации stdlib, похоже, используют код, аналогичный тому, который был выше. Является ли поведение этих реализаций undefined?