为什么每次迭代时都会调用 vector 中结构的析构函数?

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

我正在尝试使用 C++ 在 LeetCode 706. Design HashMap 中实现一个 HashMap,它是一个简单的 HashMap,具有 addremoveget 操作:

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]]

当我尝试如下使用 HashMap 时:

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);

输出显示调用了向量中每个元素的析构函数:

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

有什么我遗漏的吗?

您的 put()get()remove() 方法都犯同样的错误。

关于这个声明:

auto bucket = buckets[key % BUCKET_SIZE];

bucket 是位于索引 key % BUCKET_SIZEvectorcopy,因此它有自己的 复制 所有 Slot 个对象。

你然后循环,accessing/modifying,复制 vector,而不是原始 vector.

当该方法退出时,所有这些 副本 都会被销毁。这就是您在输出中看到的内容。

为了避免复制,您需要将上面的语句改为:

auto &bucket = buckets[key % BUCKET_SIZE];

bucket 现在将是对原始 vector 引用 ,而不是 副本