You can't directly invoke the destructor of the UnLabeledList
member like that.
If the image
constructor throws an uncaught exception, the UnLabeledList
member will be destructed automatically, if it was successfully constructed before the exception was thrown.
The correct solution is to implement a clear()
method in the linked_list
class, which you can call whenever needed, including in the copy constructor and destructor. For example:
template<...>
class linked_list {
// ...
public:
linked_list() {
// initialize the list as needed...
}
linked_list(const linked_list &src) : linked_list() {
for (each node in src) {
if (!push_back(...)) {
clear();
throw ...;
}
}
}
~linked_list() {
clear();
}
linked_list& operator=(const linked_list &rhs) {
// clear and copy the list as needed...
}
void clear() {
// free nodes as needed...
}
node* push_back(...) {
// add new node as needed...
return ...; // nullptr on error
}
//...
};
class image {
public:
linked_list<int, int> UnLabeledList;
int *SegArray = nullptr;
int Total_Segments = 0;
explicit image(int Segments) : SegArray(new int[Segments]) {
Total_Segments = Segments;
for (int i = 0; i < Segments; ++i) {
if (!UnLabeledList.push_back(i, NOT_INIT)) {
delete[] SegArray;
throw ...; // <-- UnLabeledList::~linked_list() called automatically!
}
SegArray[i] = NOT_INIT;
}
~image() {
delete[] SegArray;
} // <-- UnLabeledList::~linked_list() called automatically!
};
You also can't call a parameter-less throw;
outside of an active catch
handler. Outside of a catch
, you must throw
an actual value/object explicitly.
if (!UnLabeledList.push_back(i, NOT_INIT)) {
delete[] SegArray;
throw std::runtime_error("can't push a new node");
}