#cpp #vector
Не могли бы пожалуйста подсказать, при добавление элемента в вектор я создаю его с помощью команды new void Company::makeOrder(const char* name, const float price) { Order* new_order = new Order(name, price); orders_.push_back(new_order); } И в конце программы я хочу чтобы деструктор класса, который хранит в себе vector удалил все его элементы, и если честно не получается, может кто подскажет? class Order; class Company { public: Company(std::string name); virtual ~Company() { auto new_it = orders_.end(); for(auto it = orders_.begin(); it != new_it; it++) { delete OrderVector[*it]; } } void makeOrder(const char* name, const float price); void removeOrdersByProductName(const char* name); void hire(const Employee& employee); void fire(const char* name); void renameEmployee(const char* old_name, const char* new_name); friend std::ostream& operator<<(std::ostream& out, const Company& company); private: std::string name_; typedef std::listEmployeeList; EmployeeList employees_; typedef std::vector OrderVector; OrderVector orders_; }; std::ostream& operator<<(std::ostream& out, const Company& company);
Ответы
Ответ 1
Данное предложение delete OrderVector[*it]; не имеет смысла. OrderVector - это имя типа. Поэтому применять к нему оператор индексирования бессмысленно. Все можно сделать без всякого написания вручную цикла с помощью стандартного алгоритма std::for_each и стандартного функционального объекта std::default_delete. Вот демонстрационная программа. #include#include #include #include struct Order { ~Order() { std::cout << "Order::~Order()" << std::endl; } }; typedef std::vector OrderVector; int main() { OrderVector orders = { new Order(), new Order(), new Order() }; std::for_each( orders.begin(), orders.end(), std::default_delete () ); return 0; } Ее вывод на консоль Order::~Order() Order::~Order() Order::~Order() Если хотите использовать цикл вместо алгоритма, то достаточно написать for ( auto order : orders ) delete order; Например, #include #include struct Order { ~Order() { std::cout << "Order::~Order()" << std::endl; } }; typedef std::vector OrderVector; int main() { OrderVector orders = { new Order(), new Order(), new Order() }; for ( auto order : orders ) delete order; return 0; } Результат будет такой же, что и для программы, показанной выше. Что касается вашего собственного цикла, то правильно его будет записать следующим образом: for ( auto it = orders_.begin(); it != orders_.end(); ++it ) { delete *it; } Обратите внимание, что вместо данного объявления конструктора Company(std::string name); будет лучше записать Company( const std::string &name ); Также в виду того, что вы используете вектор указателей, вам следует либо запретить копирование объектов класса, как, например, в определении класса записать Company( const Company & ) = delete; Company & operator =( const Company & ) = delete; Либо определить их явно. Ответ 2
Если вы хотите чтобы при удалении элементов автоматически выполнялся их деструктор, то вам нужно либо завернуть указатели в "умные указатели", либо хранить в векторе не указатели, а сами объекты. Для первого варианта можно (и нужно!) использовать std::shared_ptr. Однако в этом случае деструктор Order будет вызываться не обязательно когда удаляется вектор. Он будет вызываться когда удалится последний умный указатель на его объект: #include#include typedef std::shared_ptr OrderPtr ; typedef std::vector OrderVector; OrderVector orders_; void Company::makeOrder(const char* name, const float price) { // безопасно создаем умный указатель auto new_order = std::make_shared (name, price); orders_.push_back(new_order); } Второй вариант, деструктор вектора автоматически вызовет деструкторы для каждого элемента: #include typedef std::vector OrderVector; OrderVector orders_; void Company::makeOrder(const char* name, const float price) { auto new_order = Order(name, price); orders_.push_back(new_order); } // а лучше так void Company::emplaceOrder(const char* name, const float price) { orders_.emplace_back(name, price); } Ответ 3
Что такое delete OrderVector[*it];??? Вам нужно просто в цикле сделать delete *it; Однако имейте в виду, что если с вектором такой номер еще пройдет, то вот с другим типом контейнера запросто могут возникнуть проблемы. Контейнеры с более сложной структурой (set, unordered_map и т.п.) могут требовать того, чтобы все элементы контейнера содержали корректные значения во все моменты времени. Разрушать содержимое элемента контейнера в них можно только вместе с удалением (и только после удаления) самого элемента из контейнера. В том числе именно по этой причине имеет смысл использовать "умные указатели" для хранения указателей в контейнерах.Ответ 4
Может, просто delete *it? :) Вам же надо удалять, передавая указатель, который хранится в элементе... Ваше OrderVector[*it] - это указатель, который хранится в векторе в элементе с номером, который представляет собой хранящийся в текущем элементе указатель, рассмотренный как целочисленное значение, т.е. с вероятностью 99.9999% фиг знает что, а не реальный указатель... P.S. Меня поправили - да, я не обратил внимания, что OrderVector - тип, а не вектор; мои пояснения относились к OrderVector, если бы это был вектор...
Комментариев нет:
Отправить комментарий