【发布时间】:2014-05-10 21:50:07
【问题描述】:
我无法理解为什么它没有像我预期的那样工作。可能是我使用的是 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)
};
这是 ChanceSelector 类:
using Percentage = int;
#define ChancePair(T, p, v) std::pair<Percentage, T>(p, v)
template <class T>
class ChanceSelector
{
private:
std::unordered_map<T, Percentage> _stuff;
public:
ChanceSelector()
{
}
~ChanceSelector()
{
if (_stuff.size() > 0)
_stuff.clear();
}
ChanceSelector(std::initializer_list<std::pair<Percentage, T>> list)
{
// snip for conciseness
}
T Choose()
{
// snip for conciseness
}
};
上面的代码编译得很好,但我有两个问题:
- 我不明白为什么在 std::pair 中使用 ChanceSelector 需要默认构造函数。明确地说,我似乎正在使用初始化列表调用构造函数。
- 应用程序运行时崩溃:
Unhandled exception at 0x01762fec in (my executable): 0xC0000005: Access violation reading location 0xfeeefeee.
如果我在该地图中只有一个项目,或者如果我将 affixCountChances 的定义更改为 std::unordered_map<ItemRarities, ChanceSelector<int>*>(并相应地调整其余部分),则第 2 号消失。错误将我转储到list 中的此代码:
for (_Nodeptr _Pnext; _Pnode != this->_Myhead; _Pnode = _Pnext)
{
_Pnext = this->_Nextnode(_Pnode); // <-- this line
this->_Freenode(_Pnode);
}
进一步检查揭示了析构函数中发生的错误。 _stuff 为空:
~ChanceSelector()
{
if (_stuff.size() > 0)
_stuff.clear();
}
它合法地调用了析构函数。项目正在从_stuff 中删除,但我不明白为什么它会调用析构函数。崩溃发生在所有项目都已构建并且 affixCountChances 包含所有项目之后。我认为这意味着它正在破坏它创建的所有临时对象,但我不明白它为什么会创建临时对象。
编辑:
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);
}
【问题讨论】:
-
我还没有全部读完,但听起来很像你有一个错误的移动或复制构造函数。还要小心保留标识符,例如 _stuff。
-
我已经剪掉了不相关的代码,让它变得更小。
标签: c++ unordered-map std-pair