C ++ std :: sort () Call the destructor

I overloaded my class () statement to use it as a sort sort function. When using std :: sort (), for some reason, it calls the "destructor" class several times (depending on the number of records in the vector, apparently). I described more in ~ RANK ().

#include <stdio.h> #include <stdlib.h> #include <vector> #include <algorithm> class RANK { struct COMBO { int x; }; std::vector<COMBO *> data; public: RANK() { printf("RANK()\n"); } ~RANK() { printf("~RANK()\n"); /* * Here is the problem. * Since my vector consists of pointers to COMBO objects, * I delete them upon RANK object destruction. However, * std::sort() calls RANK destructor many times and * throws some runtime error, unless commented out. */ //for (unsigned int i = 0, n = data.size(); i < n; i++) // delete data[i]; } void Add(int x) { COMBO *combo = new COMBO(); combo->x = x; data.push_back(combo); } unsigned int Size() { return data.size(); } void Sort() { std::sort(data.begin(), data.end(), *this); } int operator[](unsigned int pos) { return data[pos]->x; } bool operator()(COMBO *combo1, COMBO *combo2) { return combo1->x > combo2->x; } }; int main() { RANK rank; rank.Add(1337); rank.Add(9001); rank.Sort(); for (unsigned int i = 0, n = rank.Size(); i < n; i++) printf("%d ", rank[i]); printf("\n"); system("pause"); return 0; } 

Output (with commented destructor):

 RANK() ~RANK() ~RANK() ~RANK() ~RANK() ~RANK() 9001 1337 
+4
source share
4 answers

The first problem is that you are breaking a rule of three rules. Your class requires a non-trivial destructor to free its resources, so it must be either properly copied or uncovered to avoid using multiple objects that own the same resources. The easiest solution is to prevent copying by deleting the copy constructor and copy assignment operator:

 RANK(RANK const &) = delete; void operator=(RANK const &) = delete; 

or, if you are stuck with the compiler before 2011, declare them private without implementation.

Alternatively, you might consider storing smart pointers such as std::unique_ptr (to prevent copying) or std::shared_ptr (to allow shared ownership); if you do, then your class will have the same (safe) copy semantics as the pointer you select.

Avoiding copying will make the second problem obvious: you are using the RANK object as a comparator for std::sort . The comparator is taken by value, so the object is copied there. This can be easily fixed by defining a separate type for the comparator:

 struct CompareCOMBO { bool operator()(COMBO *combo1, COMBO *combo2) { return combol1->x > combo2->x; } }; std::sort(data.begin(), data.end(), CompareCOMBO()); 

or, if you can use lambdas:

 std::sort(data.begin(), data.end(), [](COMBO *combo1, COMBO *combo2){ return combo1->x > combo2->x; } ); 
+2
source

The comparison function in std :: sort is passed by value. Using the RANK object as a comparator, you pass a copy to std::sort (as the last value) and can copy it more than once internally.

I would suggest separating the comparison operator for COMBO from the RANK class

+6
source

Provide a copy constructor and place the breakpoint inside to see where it is being called.

+1
source

Skipping * this as a comparison object, it is copied during sorting (why don’t you see the pop-up construct, if you have a copy constructor, you will see calls).

Consider this thread to sort your objects

0
source

Source: https://habr.com/ru/post/1446060/


All Articles