C++ 将自定义类插入映射为值时出错

C++ 将自定义类插入映射为值时出错,c++,unordered-map,std-pair,C++,Unordered Map,Std Pair,我很难理解为什么它不能像我期望的那样工作。也许我正在使用Visual Studio 2013,但是嘿 这段代码是我正在编写的游戏引擎中项目随机化系统的一部分 // the chance a rarity will have a given number of affixes std::unordered_map<ItemRarities, ChanceSelector<int>> affixCountChances = { std::pair<ItemRariti

我很难理解为什么它不能像我期望的那样工作。也许我正在使用Visual Studio 2013,但是嘿

这段代码是我正在编写的游戏引擎中项目随机化系统的一部分

// the chance a rarity will have a given number of affixes
std::unordered_map<ItemRarities, ChanceSelector<int>> affixCountChances = {

std::pair<ItemRarities, ChanceSelector<int>>(ItemRarities::Cracked,
{ ChanceSelector<int>(
    { ChancePair(int, 100, 0) }) }),

std::pair<ItemRarities, ChanceSelector<int>>(ItemRarities::Normal,
{ ChanceSelector<int>(
    { ChancePair(int, 80, 0),
     ChancePair(int, 20, 1) }) }),

    // snip for conciseness (there are 3 more)
};
进一步检查发现析构函数中发生了错误<代码>\u stuff为空:

~ChanceSelector()
{
    if (_stuff.size() > 0)
    _stuff.clear();
}
它正合法地调用析构函数。正在从
\u stuff
中删除项,但我不明白为什么它会调用析构函数。崩溃发生在所有项都已构造且AffixCountOpportunity包含所有项之后。我认为这意味着它正在摧毁它创造的所有临时空间,但我不明白为什么它会创造临时空间

编辑:

ChanceSelector的构造函数:

ChanceSelector(std::initializer_list<std::pair<Percentage, T>> list)
{
    int total = 0;
    int last = 100;
    for (auto& item : list)
    {
        last = item.first;
        total += item.first;
        _stuff[item.second] = total;
    }
    // total must equal 100 so that Choose always picks something
    assert(total == 100);
}
ChanceSelector(标准::初始值设定项\u列表)
{
int-total=0;
int last=100;
用于(自动项目:列表(&T)
{
最后一项=第一项;
总计+=第一项;
_stuff[第二项]=总计;
}
//总数必须等于100,以便Choose始终选择某些内容
断言(总数=100);
}

要回答您的两个问题:

  • std::pair
    需要一个默认构造函数,因为您可以执行以下操作

    std::pair myPair();
    
    它使用默认构造函数创建类的副本(该对的值是实际值,而不是引用):

  • 0xFEEEFEEE
    表示指针本身所在的存储器已被删除(例如,处理已删除的类引用)。 此删除似乎发生在您在此发布的代码之外的某个地方。 有关更多
    幻数的信息
    请参阅

  • 编辑:

    此外,构造函数调用后,初始值设定项列表的内容不存在。您可能在那里复制了一个引用,而不是实际对象,然后实际对象被删除。
    std::unordered_映射的msvc实现使用
    std::list
    作为存储项目的基础。在给定的代码中,我无法向您提供有关此的更多信息

    编辑2:我能够用您给定的代码重现错误,它不是初始值设定项的内容。 问题似乎是初始值设定项列表中对象的生存期

    当我将无序映射对的声明从无序映射的初始值设定项列表中移出时,一切正常:

    std::pair1对(ItemRarities::Cracked,
    {选举人(
    {ChancePair(int,100,0)});
    标准::配对2(项目罕见性::正常,
    {选举人(
    {ChancePair(int,80,0),
    ChancePair(国际,20,1)});
    std::无序_映射机会={
    对1,
    pair2
    };
    

    我不完全确定这是一个问题的原因,但我认为它来自初始值设定项列表中的
    {}
    ,当离开第一个
    {}时,这些对象可能会被删除
    在输入无序地图的实际初始化器列表之前

    我还没有全部读过,但听起来很像你的移动或复制构造函数有误。还要注意保留的标识符,比如_stuff。我已经剪掉了不相关的代码,使它变得更小。好的,第一点。在2,嗯。我遗漏的代码看起来都与此无关。这里面没有删除任何东西的代码。我试着创建一个移动构造函数和赋值操作符(它调用了它们!),但是没有用。添加了一些关于初始值设定项列表的注释谢谢你的详细介绍。我已经添加了模板类的构造函数。我能够重现这个bug并添加信息,以及我是如何解决这个混乱的bug的。听起来像是一个编译器错误,但这并不奇怪,因为我很确定直到最近MSVC才允许在映射中使用初始值设定项列表。
    ~ChanceSelector()
    {
        if (_stuff.size() > 0)
        _stuff.clear();
    }
    
    ChanceSelector(std::initializer_list<std::pair<Percentage, T>> list)
    {
        int total = 0;
        int last = 100;
        for (auto& item : list)
        {
            last = item.first;
            total += item.first;
            _stuff[item.second] = total;
        }
        // total must equal 100 so that Choose always picks something
        assert(total == 100);
    }
    
    // MSVC implementation
    template<class _Ty1,class _Ty2>
    struct pair 
    {   // store a pair of values
    typedef pair<_Ty1, _Ty2> _Myt;
    typedef _Ty1 first_type;
    typedef _Ty2 second_type;
    
    pair()
    : first(), second() // Here your class gets default constructed
    {     // default construct
    }
    
    // .....
    _Ty1 first; // the first stored value
    _Ty2 second;    // the second stored value
    };
    
    std::pair<ItemRarities, ChanceSelector<int>> pair1( ItemRarities::Cracked,
        { ChanceSelector<int>(
        { ChancePair( int, 100, 0 ) } ) } );
    std::pair<ItemRarities, ChanceSelector<int>> pair2( ItemRarities::Normal,
        { ChanceSelector<int>(
        { ChancePair( int, 80, 0 ),
        ChancePair( int, 20, 1 ) } ) } );
    std::unordered_map<ItemRarities, ChanceSelector<int>> chances = {
            pair1,
            pair2
        };