'unordered_map::erase()' 总是立即调用析构函数吗?

Does `unordered_map::erase()` always call the destructor immediately?

提问人:gregschlom 提问时间:8/5/2023 更新时间:8/8/2023 访问量:134

问:

说我有.如果我调用 ,的析构函数总是会立即调用吗?或者标准库是否允许在该实例上挂起任意时间,并可能在以后重用它?std::unordered_map<int, Foo> myMap;myMap.erase(1);FooFoo

(我知道,当地图本身被摧毁时,一切都会被正确地摧毁。

C++ 析构函数无 序映射

评论

3赞 Yksisarvinen 8/5/2023
我们没有垃圾回收。调用后,键和值的生存期都已结束,并且调用了两个析构函数。erase()
4赞 PaulMcKenzie 8/5/2023
或者标准库是否允许在Foo实例上挂载,只要它愿意 - C++不能以这种方式工作。C++具有确定性销毁,不像其他依赖于垃圾回收的语言。
2赞 BiagioF 8/5/2023
这不仅仅是垃圾收集器或确定性破坏的问题。这个问题是合法的,因为(理论上)实现可能只会从“逻辑”的角度抹去价值。从技术上讲,擦除表示它会从容器中删除元素。我认为所有不疯狂的实现都会调用析构函数
1赞 user17732522 8/5/2023
"或者是否允许标准库挂在 Foo 的实例上“:如果你想要一个关于标准是否做出任何保证而不是实际实现做什么的答案,那么我建议添加标签。尽管“是否会立即调用 Foo 的析构函数”部分应该很容易回答,因为在我看来,析构函数调用应该是擦除元素的一部分。但我想也许实现可能会保留副本。我认为在这种情况下,答案不是微不足道的。language-lawyer
1赞 Mooing Duck 8/5/2023
@Yksisarvinen:它最终必须被销毁,但它似乎不必直接在方法中销毁

答:

3赞 Mooing Duck 8/5/2023 #1

我看了 https://eel.is/c++draft/#containers,似乎实际上并不需要。销毁地图、复制或移动到容器需要销毁元素,但我看到的唯一明确需要销毁的变异方法是 pop_back 和 .pop_front

从理论上讲,映射似乎可以包含“释放”节点的内部缓存,以便在将来的插入中重复使用,并且如果这样做,似乎实际上并不需要销毁和重新创建数据本身。至少在调用析构函数之前。map

这可能是 C++ 规范中的一个疏忽,如果有人实现了一个没有销毁和重新创建数据的映射,即使他们做了缓存节点,我也会感到震惊。

评论

0赞 HolyBlackCat 8/5/2023
”释放“节点的内部缓存”嗯,可以调用元素析构函数,但仍然保留节点。
0赞 Mooing Duck 8/5/2023
@HolyBlackCat:是的,最后一段说这是任何理智的缓存实现都应该做的。
0赞 Paul Sanders 8/5/2023
从理论上讲,映射似乎可以包含“释放”节点的内部缓存,以便在将来的插入中重复使用这是否违反了“假设”规则?我的意思是,析构函数可能会关闭文件或其他东西。Foo
1赞 gerum 8/5/2023
@PaulSanders:假设规则说明了优化可以以与标准不同的方式做什么。但在这种情况下,似乎不清楚标准本身的要求。
1赞 Mooing Duck 8/8/2023
@PaulSanders:标准说析构函数必须销毁所有元素,移动到和复制到必须重新分配或销毁现有元素,并且必须销毁。但仅此而已。规范并没有说其他方法必须实际销毁(至少在调用容器析构函数之前)。因此,没有假设规则适用:/clearpop_frontpop_back