I am having an issue emptying my set, so I have 3 classes like so:
class A, and 2 inherited classes B and C.
In the code I store elements in my set from the 3 types, the set is:
set<A*> objects;
so whenever I create a B element I do that:
A* b = new B(); // calling B C'tor
// and so on with A and C elements I do the exact same.`
So here comes the problem, whenever I want to erase an element, or even end the program (which calls the destructor), I don't know what I should type in the destructor, I have it like that:
set<A*>::iterator first = objects.begin();
set<A*>::iterator last = objects.end();
while (first != last) {
set<A*>::iterator to_delete = first;
objects.erase(to_delete);
delete *to_delete;
++first;
}
I have also tried putting the delete *to_delete; above objects.erase ,
also tried putting it alone ,and tried putting the erase alone without delete, but the thing is I have used new so I should use delete somewhere.
all things aren't working, the program just crashes with that, I tried keeping the D'tor empty, the program works, but I have a lot of memory leaks, I have checked that.
Please help me, I stuck with this thing. Thank you very much <3
The file:
Everything works perfectly except for the Destructor, and the removeRoom function (basically where is a delete.. also operator<< isn't working properly but I believe it's because of that thing, again I have virtual ~EscapeRoomWrapper();
#include <string>
#include <iostream>
#include <set>
#include "Company.h"
#include "ScaryRoom.h"
#include "KidsRoom.h"
#include "Exceptions.h"
using std::set;
using std::endl;
using namespace mtm;
using namespace escaperoom;
Company::Company(string name, string phoneNumber) : name(name), phoneNumber(phoneNumber) {
}
Company::~Company() {
while(!rooms.empty()) {
set<EscapeRoomWrapper*>::iterator iter = rooms.begin();
rooms.erase(iter);
delete *iter;
}
// set<EscapeRoomWrapper*>::iterator first = rooms.begin();
// set<EscapeRoomWrapper*>::iterator last = rooms.end();
// while (first != last) {
// set<EscapeRoomWrapper*>::iterator to_delete = first;
// rooms.erase(to_delete);
// delete *to_delete;
//
// ++first;
// last = rooms.end();
// }
// while (rooms.begin() != rooms.end()) {
// set<EscapeRoomWrapper*>::iterator to_delete = rooms.begin();
// rooms.erase(to_delete);
// delete *to_delete;
// }
}
Company::Company(const Company& company) : name(company.name), phoneNumber(company.phoneNumber), rooms(company.rooms) {
}
Company& Company::operator=(const Company& company) {
if (this == &company) {
return *this;
}
name = company.name;
phoneNumber = company.phoneNumber;
rooms.clear();
rooms = company.rooms;
return *this;
}
void Company::createRoom(char* name, const int& escapeTime, const int& level, const int& maxParticipants) {
try {
EscapeRoomWrapper* room = new EscapeRoomWrapper(name, escapeTime, level, maxParticipants);
rooms.insert(room);
} catch (EscapeRoomMemoryProblemException& e) {
throw CompanyMemoryProblemException();
}
}
void Company::createScaryRoom(char* name, const int& escapeTime, const int& level,
const int& maxParticipants, const int& ageLimit, const int& numOfScaryEnigmas) {
try {
EscapeRoomWrapper* room = new ScaryRoom(name, escapeTime, level, maxParticipants, ageLimit, numOfScaryEnigmas);
rooms.insert(room);
} catch (EscapeRoomMemoryProblemException& e) {
throw CompanyMemoryProblemException();
}
}
void Company::createKidsRoom(char* name, const int& escapeTime, const int& level,
const int& maxParticipants, const int& ageLimit) {
try {
EscapeRoomWrapper* room = new KidsRoom(name, escapeTime, level, maxParticipants, ageLimit);
rooms.insert(room);
} catch (EscapeRoomMemoryProblemException& e) {
throw CompanyMemoryProblemException();
}
}
set<EscapeRoomWrapper*> Company::getAllRooms() const {
return rooms;
}
void Company::removeRoom(const EscapeRoomWrapper& room) {
set<EscapeRoomWrapper*>::iterator first = rooms.begin();
set<EscapeRoomWrapper*>::iterator last = rooms.end();
while (first != last) {
if (**first == room) {
break;
}
++first;
}
if (first == last) {
throw CompanyRoomNotFoundException();
}
delete *first;
rooms.erase(first);
// delete *first; // check this
}
void Company::addEnigma(const EscapeRoomWrapper& room, const Enigma& enigma) {
set<EscapeRoomWrapper*>::iterator first = rooms.begin();
set<EscapeRoomWrapper*>::iterator last = rooms.end();
while (first != last) {
if (**first == room) {
break;
}
++first;
}
if (first == last) {
throw CompanyRoomNotFoundException();
}
(**first).addEnigma(enigma);
}
void Company::removeEnigma(const EscapeRoomWrapper& room, const Enigma& enigma) {
set<EscapeRoomWrapper*>::iterator first = rooms.begin();
set<EscapeRoomWrapper*>::iterator last = rooms.end();
while (first != last) {
if (**first == room) {
break;
}
++first;
}
if (first == last) {
throw CompanyRoomNotFoundException();
}
try {
(**first).removeEnigma(enigma);
} catch (EscapeRoomNoEnigmasException& e) {
throw CompanyRoomHasNoEnigmasException();
} catch (EscapeRoomEnigmaNotFoundException& e) {
throw CompanyRoomEnigmaNotFoundException();
}
}
void Company::addItem(const EscapeRoomWrapper& room, const Enigma& enigma, const string& element) {
set<EscapeRoomWrapper*>::iterator first_room = rooms.begin();
set<EscapeRoomWrapper*>::iterator last_room = rooms.end();
while (first_room != last_room) {
if (**first_room == room) {
break;
}
++first_room;
}
if (first_room == last_room) {
throw CompanyRoomNotFoundException();
}
vector<Enigma>::iterator first = (**first_room).getAllEnigmas().begin();
vector<Enigma>::iterator last = (**first_room).getAllEnigmas().end();
while (first != last) {
if (*first == enigma) {
break;
}
++first;
}
if (first == last) {
throw CompanyRoomEnigmaNotFoundException();
}
(*first).addElement(element);
}
void Company::removeItem(const EscapeRoomWrapper& room, const Enigma& enigma, const string& element) {
set<EscapeRoomWrapper*>::iterator first_room = rooms.begin();
set<EscapeRoomWrapper*>::iterator last_room = rooms.end();
while (first_room != last_room) {
if (**first_room == room) {
break;
}
++first_room;
}
if (first_room == last_room) {
throw CompanyRoomNotFoundException();
}
vector<Enigma>::iterator first = (**first_room).getAllEnigmas().begin();
vector<Enigma>::iterator last = (**first_room).getAllEnigmas().end();
while (first != last) {
if (*first == enigma) {
break;
}
++first;
}
if (first == last) {
throw CompanyRoomEnigmaNotFoundException();
}
try {
(*first).removeElement(element);
} catch (EnigmaNoElementsException& e) {
throw CompanyRoomEnigmaHasNoElementsException();
} catch (EnigmaElementNotFoundException& e) {
throw CompanyRoomEnigmaElementNotFoundException();
}
}
set<EscapeRoomWrapper*> Company::getAllRoomsByType(RoomType type) const {
set<EscapeRoomWrapper*> filtered_set;
set<EscapeRoomWrapper*>::iterator first_room = rooms.begin();
set<EscapeRoomWrapper*>::iterator last_room = rooms.end();
EscapeRoomWrapper* ptr = NULL;
while (first_room != last_room) {
if (type == BASE_ROOM) {
if (dynamic_cast<ScaryRoom*>(*first_room) == ptr
&& dynamic_cast<KidsRoom*>(*first_room) == ptr) {
filtered_set.insert(*first_room);
}
}
if (type == SCARY_ROOM) {
if (dynamic_cast<ScaryRoom*>(*first_room) != ptr) {
filtered_set.insert(*first_room);
}
}
if (type == KIDS_ROOM) {
if (dynamic_cast<KidsRoom*>(*first_room) != ptr) {
filtered_set.insert(*first_room);
}
}
++first_room;
}
return filtered_set;
}
EscapeRoomWrapper* Company::getRoomByName(const string& name) const {
set<EscapeRoomWrapper*>::iterator first_room = rooms.begin();
set<EscapeRoomWrapper*>::iterator last_room = rooms.end();
while (first_room != last_room) {
if ((**first_room).getName() == name) {
break;
}
++first_room;
}
if (first_room == last_room) {
throw CompanyRoomNotFoundException();
}
return *first_room;
}
std::ostream& mtm::escaperoom::operator<<(std::ostream& output, const Company& company) {
output << company.name << " : " << company.phoneNumber << endl;
set<EscapeRoomWrapper*>::iterator first_room = company.getAllRooms().begin();
set<EscapeRoomWrapper*>::iterator last_room = company.getAllRooms().end();
while (first_room != last_room) {
output << **first_room << endl;
++first_room;
}
return output;
}
The problem is that
objects.end()changes when something is removed from the set and the value stored inlastis invalidated.You can fix your code as follows:
In general you shouldn't use raw pointers at all in the set. Rather use something like
in your program. So you don't need to care for the correct deallocation of the objects at all.