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);