我正在使用C ++中动态分配的数组构建一个简单的列表。我有一个函数remove(int item)
,它应该删除列表中出现的所有item
。但是,如果我在数组中创建一个从0
迭代到length
的循环,我担心我会超出数组的边界,因为length
在删除项目时会发生变化:< / p>
int List::pop(int index)
{
int retval = data[index];
for (int i = index; i < length; i++)
data[i] = data[i+1];
length--;
return retval;
}
void List::remove(int item)
{
for (int i = 0; i < length; i++) {
if (data[i] == item)
pop(i);
}
因此,如果我在remove(6)
上调用了array[6][4][2][6][1][3][5][6]
,那么C ++会在for
之后使用remove()
的更新值更新length
循环pop()
1}?或者它会在调用remove()
时保持与最初传递给它的值相同吗?
答案 0 :(得分:3)
另一种解决方案是反向搜索。只保留那些与项目不相同的项目。
void List::remove(int item)
{
int insert = 0;
for (int i = 0; i < length; i++) {
if (data[i] != item)
data[insert++] = data[i];
}
length = insert;
}
答案 1 :(得分:2)
从数组末尾开始,然后向后返回起始位置。或者,请致电pop(i--)
而不是pop(i)
。这会备份i
,因此您不会跳过列表中的任何元素(包括最后一项)。
第一种方法的优点是你不会浪费时间向下移动最终会被移除的元素。
答案 2 :(得分:2)
在循环的每次迭代之前,完整地计算条件表达式i < length
。 C ++编译器不会缓存i
,也不会缓存length
进行此评估。只要length
变量被正确更新,这个表达式就不允许i
超出数组的范围。
但这对跳过元素问题没有帮助。要做到这一点,我会切换到while循环。
int i = 0;
while (i < length) {
if (data[i] == item) {
pop(i);
} else {
i++;
}
}
在这种情况下,如果我们pop
项目,我们不会增加。这样,索引保持在同一个位置,并且能够捕获在数组中彼此相邻的重复项