Реализация своего vector C++, удаление последнего элемента через pop_back()
#include <iostream>
#include <cstdlib>
namespace s21 {
template <class T>
class vector {
public:
using value_type = T;
using reference = T&;
using const_reference = const T&;
using iterator = T*;
using const_iterator = const T*;
using size_type = std::size_t;
public:
vector();
~vector();
void push_back(const_reference value);
const_reference back();
void pop_back();
private:
T *array_;
size_t size_;
size_t capacity_;
};
}
namespace s21 {
template <class T>
vector<T>::vector() : array_(new T[1]), size_(0), capacity_(1) {}
template <class T>
vector<T>::~vector() {
std::cout << array_[5];
delete [] array_;
}
template <class T>
void vector<T>::push_back(const_reference value) {
if (size_ == capacity_) {
capacity_ += 10;
T *tmp = new T[capacity_];
std::copy(array_, array_ + size_, tmp);
delete [] array_;
array_ = tmp;
}
array_[size_] = value;
size_++;
}
template <class T>
typename vector<T>::const_reference vector<T>::back() {
if (size_ == 0) {
throw(std::out_of_range("vector is empty"));
}
return array_[size_ - 1];
}
template <class T>
void vector<T>::pop_back() {
if (size_ == 0) {
throw(std::out_of_range("Vector is empty"));
}
size_--;
array_[size_].~T(); // тут пытаюсь деструктор на последний элемент вызвать, но похоже оно не работает
// так как все равно потом к этому элементу можно обратиться
}
}
int main() {
s21::vector <int> steck_;
steck_.push_back(1);
steck_.push_back(2);
steck_.push_back(3);
steck_.push_back(4);
steck_.push_back(5);
steck_.push_back(5);
steck_.push_back(5);
steck_.pop_back();
steck_.pop_back();
steck_.pop_back();
steck_.pop_back();
std::cout << steck_.back() << std::endl;
return 0;
}
Погуглил, кто-то пишет, что достаточно просто уменьшить size, а с самим элементом ничего не делать, другие пишут, что оригинальный vector таки удаляет этот элемент. Нашёл вот такой способ array_[size_].~T(), но судя по всему, он не работает? Я все ещё могу обратиться к как бы удалённым элементам (в деструкторе ~vector() для проверки вывожу элемент, который должен был удалиться).
Ответы (1 шт):
При удалении вашего вектора как такового в его деструкторе у вас вызывается
delete [] array_;
Т.е. будет вызван деструктор для каждого элемента массива. Так имеет ли смысл вызывать деструктор при pop_back(), в особенности рискуя тем, что такой деструктор будет вызван дважды (второй раз при удалении вектора) и для чего-то посложнее int может привести к массе неприятностей? Конечно, можно вызывать деструктор и в pop_back(), но тогда надо принять специальные меры во избежание упомянутых неприятностей.
Как именно этого добиться — отдельный вопрос, в обычном векторе из стандартной библиотеки этим занимается аллокатор.
Теперь об обращении к удаленным... Как вы себе представляете невозможность обращения? Что это вообще значит — удаленный элемент? Особенно простой, типа int, который деструктор не запортит (а вообще ничего не сделает)? Как физическое вырезание куска памяти из платы? :) Память-то на месте, так почему к ней нельзя обратиться? Можно вообще обратиться к памяти по "левому" адресу, просто это будет неопределенное поведение.
Т.е. окончательный ответ на вторую часть вашего вопроса остается открытым, пока мы не утрясем терминологическую путаницу и ваши ожидания. Итак, что такое в вашем представлении "удаленный элемент массива"? В массиве int a[] = { 1,2,3,4} как вы себе представляете удаление элемента 4?