C ++在for循环中删除列表的成员

时间:2018-01-20 02:15:47

标签: c++ for-loop

考虑你有一个带有两个函数foo()和goo()的类Base,以及一个在创建Base对象时被赋值为0或1的bool布尔值。然后我们有以下内容:

//declaring a list
std::list<Base*> base;
//creating 10 objects of Base and storing on the list
for (int i = 0; i < 10; i++)
{
    Base *b = new Base();
    base.push_back(b);
}
for (auto i = base.begin(); i != base.end();)
{
    Base *e = *i;

    e->foo();
    e->goo();
    if (e->boolean == false)
    {
        i = base.erase(i);
        delete e;
    }
    else
        i++;
}

第一个问题:程序员为什么省略for循环中的第三个参数?是隐式的吗? 第二个问题:请解释我何时使用擦除和/或删除或两者以及为什么在此片段中有必要使用擦除和/或删除。还要解释我需要Base * e = * i;而不只是调用i-&gt; foo(); i-&gt; goo()直接。非常感谢你:))

2 个答案:

答案 0 :(得分:1)

第一个问题

注意i = base.erase(i);。擦除后,i无效,它指向的列表项已消失,因此erase返回擦除项目后的下一个项目,以允许您继续浏览列表。由于i已经引用了i++i++循环中向其添加额外for的内容,因此会跳过列表中的项目。

如果没有删除任何项目,则在其他情况下处理常规i++

请查看Erase-Remove idiom以获得更好的方法。

第二个问题

i是指向Base 1 的指针的迭代器,因此i->foo()会尝试在指针上调用foo,指针有没有foo。而不是怜悯foo,你必须首先取消引用迭代器,然后取消引用指针。

你不能i->->foo();,但你可以(*i)->foo();(*i)取消引用迭代器并为您提供->foo()部分的指针。

Base *e = *i; 

缓存解除引用的迭代器,所以

e->foo();

相同
(*i)->foo();

也许它使代码更容易阅读。也许它有一个小的性能优势。取决于(*i)所需的金额以及您提供的名称的描述性ee作为变量名称很糟糕,因为你不得不问这个问题。一个好的变量名称会告诉你发生了什么。

1 顺便说一下,你几乎不想这样做。让库容器包含对象的实例,而不是指针,以便它们可以为您管理所有内存。简化内存管理是其设计目标的重要组成部分。

然而,在这种情况下,名称Base表明多态性正在发挥作用。多态对象列表是您唯一需要指针容器的时间。但请查看using smart pointers以管理任何动态分配的多态对象的生命周期。

答案 1 :(得分:0)

如果增量表达式为&#39;为&#39;省略,根本没有采取任何行动。

for(init ; test; increment)

总是等同于:

{
  init ;
  while(test)
    body
}

周围的大括号构成了将初始化变量限制为for语句

的C ++标准行为