C++ 将自定义类插入映射为值时出错
我很难理解为什么它不能像我期望的那样工作。也许我正在使用Visual Studio 2013,但是嘿 这段代码是我正在编写的游戏引擎中项目随机化系统的一部分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
// 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
};