C++ 如何销毁通过'构造的无析构函数类型;新位置';
因此,我构建了一个类,我打算使用该类使用C++ 如何销毁通过'构造的无析构函数类型;新位置';,c++,c++11,stl,C++,C++11,Stl,因此,我构建了一个类,我打算使用该类使用std::aligned_storage为一个“Variant”类存储最多16个字节的不同类型。理论上,它应该能够存储任何吊舱类型和常见容器,如std::string和std::map 我看了这里的代码示例,它似乎正是为我想要的东西而设计的: 我的版本,基本上: class Variant { public: Variant() { /* construct */ } Variant(std::map<int,int> v) {
std::aligned_storage
为一个“Variant”类存储最多16个字节的不同类型。理论上,它应该能够存储任何吊舱类型和常见容器,如std::string
和std::map
我看了这里的代码示例,它似乎正是为我想要的东西而设计的:
我的版本,基本上:
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;
};
在我看来,我正在做完全相同的事情,无视模板匿名性。问题是,std::map
没有任何std::map::~map()
析构函数方法,只有一个std::map::~\u树
,这显然不是为了直接使用。那么,在cppreference.com示例代码中,如果T
是一个std::map
,那么~T()
将调用什么,对于std::aligned_storage
中已知类型的对象,调用析构函数的正确方法是什么?还是我把事情复杂化了,这些STL容器中的clear()
方法保证了完全销毁的效果
或者,有没有更简单的方法?因为我可能误解了我对std::aligned_storage
的预期用途
我不确定调用什么来代替~T()
您的类型名为map
:
reinterpret_cast<std::map<int, int>*>(&m_data)->~map();
reinterpret_cast(&m_数据)->~map();
如果它让您感觉更好,您可以将其放入函数模板中:
template <class T>
void destroy_as(void* p) {
static_cast<T*>(p)->~T();
}
destroy_as<std::map<int, int>>(&m_data);
模板
无效销毁作为(无效*p){
静态_cast(p)->~T();
}
销毁_as(&m_数据);
问题是,std::map
没有任何std::map::~map()
destructor方法
它可能是由编译器生成的,但类型肯定有一个析构函数。所有类型都有析构函数。有些可能是显式的或隐含的delete
d,但它们是存在的
请注意,您的
aligned_存储
太小,无法存储map
,sizeof(std::map)
大于16 听起来您已经阅读了定义了std::map
的头文件,并认为std::map
没有析构函数,因为您找不到析构函数的声明
但是,在C++中,声明没有析构函数的类型将有编译器隐式声明的析构函数。这个隐式析构函数将调用基和非静态成员的析构函数。听起来像是库实现中的
std::map
是\u树上的一层薄薄的一层。因此,销毁地图所需要做的就是销毁这棵树。因此,编译器的默认析构函数就完成了这个任务
在您的情况下,允许编写->~map()
,它将调用隐式定义的析构函数,映射将被正确销毁。您也可以将此语法用于标量类型,例如int
(但由于某些原因,不能使用数组)。是什么让您认为没有std::map::~map()
?当然有。啊,我还想问这是否与我的编译器有关,但一定是编辑掉了。那么,我在这里看到的是Visual Studio 2015对C++11的支持还是什么问题?因为头文件中几乎肯定没有@BrianAll类有一个析构函数(如果没有的话,编译器会隐式声明),您还可以在非类类型上使用~t()
语法,因为它被定义为非opAh,所以我只是因为它在VisualStudio的Intellisense建议和头文件本身中不存在而过早地推迟了。我想我只是在想,明确摧毁某些物体确实有问题。哦!在visualstudios的实现中,它似乎是12个,我并不感到惊讶,它在所有方面都不一样。我根据我的源代码改编了我的示例,它使用的是std::string
(正如它使用的std::string::~basic_string()
,使情况不再是一个明显的难题)。我还计划添加std:map
支持,这提醒我在继续之前需要更深入地了解,谢谢。
template <class T>
void destroy_as(void* p) {
static_cast<T*>(p)->~T();
}
destroy_as<std::map<int, int>>(&m_data);