我已经开始为练习编写一个简单的控制台Yahtzee游戏。我只是对这个功能是否会泄漏内存有疑问。每次需要重新滚动骰子时都会调用滚动功能。
它的作用是创建一个动态数组。第一次使用它会存储5个随机值。对于下一次运行,除了你想要保留的骰子外,它只会重新滚动。我有另一个功能,但由于它与这个问题无关,我把它留了出来
主要功能
int *kast = NULL; //rolled dice
int *keep_dice = NULL; //which dice to re-roll or keep
kast = roll(kast, keep_dice);
delete[] kast;
这是函数
int *roll(int *dice, int *keep) {
srand((unsigned)time(0));
int *arr = new int[DICE];
if(!dice)
{
for(int i=0;i<DICE;i++)
{
arr[i] = (rand()%6)+1;
cout << arr[i] << " ";
}
}
else
{
for(int i=0;i<DICE;i++)
{
if(!keep[i])
{
dice[i] = (rand()%6)+1;
cout << "Change ";
}
else
{
keep[i] = 0;
cout << "Keep ";
}
}
cout << endl;
delete[] arr;
arr = NULL;
arr = dice;
}
return arr;
}
答案 0 :(得分:12)
是的,它可以泄漏。例如,使用cout
可以抛出异常,如果是,则永远不会调用delete
。
您可能需要考虑返回std::vector
,而不是自己分配动态数组。更好的是,将您的函数转换为适当的算法,该算法采用迭代器(在本例中为back_insert_iterator
)并将其输出写入其中。
编辑:仔细看一下,我觉得有必要指出我完全不喜欢这段代码的基本结构。你有一个功能,它真的做了两种不同的事情。您还有一对阵列,它们依赖于并行寻址。我将其重组为两个单独的函数,roll
和re_roll
。我将数据重组为结构数组:
struct die_roll {
int value;
bool keep;
die_roll() : value(0), keep(true) {}
};
要进行初始滚动,您可以将这些向量(或数组,如果您真正坚持的话)传递给填充初始值的roll
函数。要进行重新滚动,请将向量传递给re-roll
,然后重新滚动以获取keep
成员已设置为false
的任何die_roll的新值。
答案 1 :(得分:4)
使用(stack-allocated)std::vector
而不是数组,并将对它的引用传递给函数。这样,你就可以确定它不会泄漏。
答案 2 :(得分:4)
分配内存的方式令人困惑:函数内部分配的内存必须通过函数外部的代码释放。
为什么不重写这样的东西:
int *kast = new int[DICE]; //rolled dice
bool *keep_dice = new bool[DICE]; //which dice to re-roll or keep
for (int i = 0; i < DICE; ++i)
keep_dice[i] = false;
roll(kast, keep_dice);
delete[] kast;
delete[] keep_dice;
这样可以很好地匹配您的new
和delete
。关于函数:因为我们将keep_dice
全部设置为false
,这两个参数都不是NULL
,它总是修改dice
而不是返回一个新数组,它简化为:
void roll(int *dice, int *keep) {
for(int i=0;i<DICE;i++)
{
if(keep[i])
{
keep[i] = false;
cout << "Keep ";
}
else
{
dice[i] = (rand()%6)+1;
cout << "Change ";
}
}
cout << endl;
}
此外,您应该将srand
电话移至程序的开头。重播非常不利于随机性。
答案 3 :(得分:0)
我的建议是抽出时间购买/借阅并阅读Scott Meyers Effective C ++ 3rd Edition。为了成为一名高效的C ++程序员,您将节省数月的痛苦。我从个人的,痛苦的经历中说话。