set.clear() 在删除元素之前调用所包含元素的析构函数
set.clear() calls destructors of contained elements before removing the element
在下面的代码中,我希望断言能够通过,但它没有。
这与记录的unique_ptr::reset的行为不同,我发现它非常令人惊讶。
我做错了什么还是错误?这是一个问题,因为如果删除相同的元素增益,析构函数将被调用两次。
#include <set>
#include <memory>
struct F
: std::enable_shared_from_this<F>
{
static int destructor_count;
static std::set<std::shared_ptr<F>> container;
F() {}
~F() {
assert(container.size() == 0);
container.clear(); // This will delete the same pointer twice.
destructor_count--;
}
};
int F::destructor_count = 0;
std::set<std::shared_ptr<F>> F::container;
int main()
{
F::container.insert(std::shared_ptr<F>(new F));
F::container.clear();
return 0;
}
编译器信息:
libstdc++6-4.6-dev
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
记录unique_ptr
这样做是有原因的:它比通常对标准库的其余部分有更强的保证。如果相同的规则适用于所有类型,则无需专门针对unique_ptr
进行说明。
代码在运行对F::container.clear()
的另一个调用时递归调用F::container.clear()
。这不能保证有效:
17.6.5.8 重入 [重入]
除非本标准中明确指定,否则由实现定义,标准C++库中的哪些函数可以递归重新输入。
现在不幸的是,libstdc++ 无法记录哪些函数可以递归重新输入,因此假设没有函数可以更安全,因此您的断言是不正确的。
在清除容器时调用 F 的析构函数,在此期间容器不为空,因此断言失败。
我不确定你为什么会期望这个断言是正确的。您不需要知道容器如何保存和销毁内存的详细信息。你不应该对std::set::clear()
期间发生的事情做出假设,只相信在它完成后,所有的析构函数都会被调用,std::set::size()
将返回 0。
在这篇多布斯博士的旧文章《STL的红黑树》中,描述了std::set
背后的支持数据结构。在整个树为空之前,节点将被删除(并且它们的内容被破坏),但请放心,在std::set::clear()
结束时,所有析构函数都将被调用,std::set::size()
将返回 0。
注意:std::set
的其他实现可能使用不同的支持数据结构,红黑树只是可能的实现。
- 如何为 std::vector 分配内存,然后稍后为某些元素调用构造函数?
- C++:带有大括号初始化列表的函数调用表达式 - 标准是否规定在单个元素列表的微不足道的情况下忽略大括号?
- 使用并行参数向量调用元素向量的成员函数
- 调用 erase() 函数是否也会在擦除元素之前更改迭代器值?
- 如何在不迭代的情况下对数组中的每个元素调用方法
- 为什么 delete[] 不等同于 C++ 中为每个元素调用 delete?
- C++为每个元素调用任意函数
- C 如何使用数组的元素调用类
- boost::lockfree-为排队的元素调用析构函数
- 如何使用提升 lambda 对集合中的每个元素调用方法?
- 为集合中的每个元素调用具有多个参数的函数
- 对C++向量的每个元素调用函数
- 为构造的std::vector中的每个元素调用默认构造函数
- c++11:用向量的元素调用变差函数
- 对std::array中的元素调用用户定义的构造函数
- 对一个对象上的每个元组元素调用函数,不进行递归
- 当每个字符串由"new char[]"创建时,如何对"vector<string>"的元素调用"delete"?
- 作为数组元素调用函数
- std::list 的擦除成员函数是否为所有存储的元素调用析构函数?
- 对集合中的每个元素调用print的通用算法