所以我构建了一个类,我打算使用std::aligned_storage
来存储最多16个字节的不同类型,以用于变体'类。从理论上讲,它应该能够存储任何POD类型和常见容器,例如std::string
和std::map
。
我按照此处找到的代码示例进行操作,看起来它的确是为了我正在寻找的内容:http://en.cppreference.com/w/cpp/types/aligned_storage
我的版本,基本上是:
class Variant {
public:
Variant() { /* construct */ }
Variant(std::map<int,int> v) {
new(&m_data) std::map<int,int>(v); // construct std::map<int,int> at &m_data
m_type = TYPE_MAP;
}
~Variant() {
if (m_type == TYPE_MAP) {
// cool, now destruct..?
reinterpret_cast<std::map<int, int>*>(&m_data)->~/*???????????????*/();
}
}
private:
// type of object in m_data
enum Type m_type;
// chunk of space for allocating to
std::aligned_storage<16, std::alignment_of<std::max_align_t>::value>::type m_data;
};
我的问题伴随着破坏。正如您在/*???????????????*/
所看到的,我不确定在cppreference.com示例中代替~T()
应该拨打什么电话:
reinterpret_cast<const T*>(data+pos)->~T(); // I did the same thing except I know what T is, is that a problem is it?
在我看来,我做了完全相同的事情,无视模板匿名。问题是,std::map
没有任何std::map::~map()
析构函数方法,只有std::map::~_Tree
,这显然不是为了直接使用。那么,在cppreference.com示例代码中,如果~T()
是T
,那么std::map<int,int>
会调用什么,以及我为一个对象调用析构函数的正确方法是什么std::aligned_storage
中的已知类型?或者我是否使事情复杂化并且这些STL容器中的clear()
方法是否相当于完全销毁?
或者,有没有更简单的方法呢?因为我可能误解了我对std::aligned_storage
的预期用法的看法。
答案 0 :(得分:5)
听起来你已经读过定义了std::map
的头文件,并认为std::map
没有析构函数,因为你找不到析构函数的声明。
但是,在C ++中,没有声明析构函数的类型将具有编译器声明的析构函数隐式。这个隐式析构函数将调用基数和非静态成员的析构函数。听起来您的库实现中的std::map
是_Tree
上的薄层。因此,破坏地图需要做的就是破坏树。因此,编译器的默认析构函数可以解决问题。
允许在你的情况下编写->~map()
,它将调用隐式定义的析构函数,并且地图将被正确销毁。您也可以将此语法用于标量类型,例如int
(但由于某种原因,不是数组)。
答案 1 :(得分:2)
我不知道该怎么称呼
~T()
您的类型,名为map
:
reinterpret_cast<std::map<int, int>*>(&m_data)->~map();
如果它让你感觉更好,你可以放入一个功能模板:
template <class T>
void destroy_as(void* p) {
static_cast<T*>(p)->~T();
}
destroy_as<std::map<int, int>>(&m_data);
问题是,
std::map
没有任何std::map::~map()
析构函数方法
它可能是编译器生成的,但类型确定具有析构函数。所有类型都有析构函数。有些可能是明确的或实现的delete
d,但它们存在。
请注意,aligned_storage
太小,无法存储map
,sizeof(std::map)
大于16。