stl::unordered_map 和 stl::vector 的销毁有何不同
What differs in the destruction of stl::unordered_map and stl::vector
我正在寻找更详细的答案,而不是UB是UB。
我有一段遗留代码,我知道它是异常的罪魁祸首。我们之前对一个向量进行了内存设置,一旦它被更改为unordered_map它就会在销毁时抛出一个异常。源代码中的哪些因素使模因设置向量与unordered_map不同?它们都与连续的记忆相互作用......
在我们的代码中,我们有这个。(对于伪代码,我深表歉意,但这一点应该还是可以理解的......
class B
{
std::vector<CustomObject> vect;
};
struct STRUCT_A
{
B b;
};
稍后我们这样做...
STRUCT_A m_struct_a;
memset(&m_struct_a, 0, sizeof(STRUCT_A));
即使我们设置了一个 stl::container,这也工作得很好!但是,如果我们将类 B 更改为具有映射,则析构函数上会发生异常。
class B
{
std::map<CustomObject> vect;
};
所以我认为这与向量是连续的有关,所以我把它改成了unordered_map
class B
{
std::unordered_map<CustomObject> vect;
};
析构函数上仍会引发异常。我觉得这很有趣,并认为这是一个值得问的好问题......
是的,::memset
包含 STL 容器的类的实例确实是一种绝对疯狂的行为。
更一般地说,您只能在可复制的对象上调用memset
。否则,程序的行为是未定义的。
有关更多详细信息,请参阅 http://en.cppreference.com/w/cpp/string/byte/memset 和 http://en.cppreference.com/w/cpp/types/is_trivially_copyable
查看实现容器的源代码。
在 libstdc++ 中,std::vector
的析构函数调用范围中的每个元素CustomObject::~CustomObject()
[begin(), end())
,然后解除分配内存。由于memset
vector
为 0,因此begin() == end() == 0
,范围为空,并且永远不会调用成员的析构函数。同样,释放也很好,因为它会在解除分配之前检查存储是否为非空。
在std::map
中,析构函数试图遍历_Rb_tree
节点,但失败是因为根节点有空指针。在std::unordered_map
中,析构函数在存储桶数组上调用__builtin_memset
,该数组失败,因为指向数组的指针已被清除。
- Python中的for循环与C++有何不同
- 在C++中释放内存期间,迭代器与指针有何不同
- -fvisibility-inline-hidden 与 gcc 中的 -fvisibility=hidden 有何不同
- 收益率和回报有何不同?
- 覆盖私有功能,它与受保护功能有何不同?
- 无论代码长度如何,以下代码的内存要求有何不同?
- stl::unordered_map 和 stl::vector 的销毁有何不同
- C++ 友元函数在内存位置上有何不同?
- C 是否具有接口类概念,如果它在那里,那么它与Java接口类别有何不同
- std::u8string与std::string有何不同?
- 两种类型转换有何不同?
- 这个语句到底是什么意思 stack<int, list<int> > 它与 stack 有何不同<int>?
- 英特尔®事务同步扩展新指令 (TSX-NI) 与英特尔 TSX 有何不同?
- 指向成员函数的指针与指向数据成员的指针有何不同
- 字符 * 和字符串在C++中有何不同?(在描述中编写代码)
- 在C++中,Mixin与面向策略的设计有何不同
- "cin>>"与"cin.get"有何不同?还是不是?
- C++11: boost::make_tuple 与 std::make_tuple 有何不同?
- 双重列表复制构造函数:与单一列表复制构造函数有何不同
- 在C++中声明可见性/访问权限的方法有何不同