Home > Net >  Why the destructor of a struct in vector are called every time I iterate over them?
Why the destructor of a struct in vector are called every time I iterate over them?

Time:04-22

I'm trying to implement a HashMap in LeetCode 706. Design HashMap with C , it's a simple HashMap with add, remove, get operations:

struct Slot {
    int key;
    int val;
    void setValue(int v) {
        cout << "-set " << v << "fo SV"<<endl;
        val = v;
    }
    ~Slot() {
        cout << "dtor Slot " << key << endl;
    }
};

#define BUCKET_SIZE 769
class MyHashMap {
private:
    vector<vector<Slot>> buckets;
    //const int BUCKET_SIZE;
public:
    MyHashMap() :buckets(BUCKET_SIZE, vector<Slot>()) {
    }
    
    void put(int key, int value) {
        auto bucket = buckets[key % BUCKET_SIZE];
        cout << "Add: use bucket " << (key % BUCKET_SIZE) << endl;
        
        for (auto iter = bucket.begin(); iter != bucket.end(); iter  ) {
            if (iter->key == key) {
                cout << "Add: update key " << key << " with value " << value << endl;
                *iter = Slot{key, value};
                return;
            }
        }
        
        cout << "Add: push key " << key << " to back with value " << value << endl;
        buckets[key % 769].push_back(Slot{key, value});
    }
    
    int get(int key) {
        auto bucket = buckets[key % BUCKET_SIZE];
        for (auto iter = bucket.begin(); iter != bucket.end(); iter  ) {
            if (iter->key == key) {
                return iter->val;
            }
        }
        
        return -1;
    }
    
    void remove(int key) {
        auto bucket = buckets[key % BUCKET_SIZE];
        for (auto iter = bucket.begin(); iter != bucket.end(); iter  ) {
            if (iter->key == key) {
                cout << "Remove: remove " << key << endl;
                bucket.erase(iter);
                return;
            }
        }
    }
};
["MyHashMap","put","put","get","get","put","get","remove","get"]
[[],[1,10],[2,2],[1],[3],[2,1],[2],[2],[2]]

When I tried to use the HashMap as below:

MyHashMap* obj = new MyHashMap();
obj->put(1, 10);
obj->put(2, 2);
obj->get(1);
obj->get(3);
obj->put(2, 1);
obj->get(2);
obj->remove(key);
obj->get(2);

The output shows that the destructor of every element in the vector are called:

Add: use bucket 1
Add: push key 1 to back with value 10
dtor Slot 1
Add: use bucket 2
Add: push key 2 to back with value 2
dtor Slot 2
dtor Slot 1
Add: use bucket 2
Add: update key 2 with value 1
dtor Slot 2
dtor Slot 2
dtor Slot 2
Remove: remove 2
dtor Slot 2
dtor Slot 2
dtor Slot 1
dtor Slot 2

Is there anything I have missed?

CodePudding user response:

Your put(), get() and remove() methods all making the same mistake.

On this statement:

auto bucket = buckets[key % BUCKET_SIZE];

bucket is a copy of the vector located at index key % BUCKET_SIZE, and thus it makes its own copy of all of the Slot objects.

You are then looping through, and accessing/modifying, that copied vector, not the original vector.

When the method exits, all of those copies get destroyed. That is what you are seeing in your output.

To avoid the copies, you need to change the above statement to this instead:

auto &bucket = buckets[key % BUCKET_SIZE];

bucket will now be a reference to the original vector, not a copy.

  • Related