考虑你有一个带有两个函数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()直接。非常感谢你:))
答案 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)
所需的金额以及您提供的名称的描述性e
。 e
作为变量名称很糟糕,因为你不得不问这个问题。一个好的变量名称会告诉你发生了什么。
1 顺便说一下,你几乎不想这样做。让库容器包含对象的实例,而不是指针,以便它们可以为您管理所有内存。简化内存管理是其设计目标的重要组成部分。
然而,在这种情况下,名称Base
表明多态性正在发挥作用。多态对象列表是您唯一需要指针容器的时间。但请查看using smart pointers以管理任何动态分配的多态对象的生命周期。
答案 1 :(得分:0)
如果增量表达式为&#39;为&#39;省略,根本没有采取任何行动。
for(init ; test; increment)
体
总是等同于:
{
init ;
while(test)
body
}
周围的大括号构成了将初始化变量限制为for语句
的C ++标准行为