为什么每次迭代时都会调用 vector 中结构的析构函数?
Why the destructor of a struct in vector are called every time I iterate over them?
我正在尝试使用 C++ 在 LeetCode 706. Design HashMap 中实现一个 HashMap,它是一个简单的 HashMap,具有 add
、remove
、get
操作:
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_SIZE
的 vector
的 copy,因此它有自己的 复制 所有 Slot
个对象。
你然后循环,accessing/modifying,复制 vector
,而不是原始 vector
.
当该方法退出时,所有这些 副本 都会被销毁。这就是您在输出中看到的内容。
为了避免复制,您需要将上面的语句改为:
auto &bucket = buckets[key % BUCKET_SIZE];
bucket
现在将是对原始 vector
的 引用 ,而不是 副本 。
我正在尝试使用 C++ 在 LeetCode 706. Design HashMap 中实现一个 HashMap,它是一个简单的 HashMap,具有 add
、remove
、get
操作:
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_SIZE
的 vector
的 copy,因此它有自己的 复制 所有 Slot
个对象。
你然后循环,accessing/modifying,复制 vector
,而不是原始 vector
.
当该方法退出时,所有这些 副本 都会被销毁。这就是您在输出中看到的内容。
为了避免复制,您需要将上面的语句改为:
auto &bucket = buckets[key % BUCKET_SIZE];
bucket
现在将是对原始 vector
的 引用 ,而不是 副本 。