Gal*_*man 8 c++ linux stl visual-studio-2005 map
请考虑以下情形:
map(T,S*) & GetMap(); //Forward decleration
map(T, S*) T2pS = GetMap();
for(map(T, S*)::iterator it = T2pS.begin(); it != T2pS.end(); ++it)
{
if(it->second != NULL)
{
delete it->second;
it->second = NULL;
}
T2pS.erase(it);
//In VS2005, after the erase, we will crash on the ++it of the for loop.
//In UNIX, Linux, this doesn't crash.
}//for
Run Code Online (Sandbox Code Playgroud)
在我看来,在VS2005中,在"擦除"之后,迭代器将等于end(),因此在尝试增加它时崩溃.在这里呈现的行为中,编译器之间是否存在真正的差异?如果是这样,"擦除"之后的迭代器将在UNIX/Linux中等于什么?
谢谢...
Joh*_*itb 21
是的,如果擦除迭代器,那么迭代器会得到一个所谓的奇异值,这意味着它不再属于任何容器.你不能再增加,减少或读出它.执行该循环的正确方法是:
for(map<T, S*>::iterator it = T2pS.begin(); it != T2pS.end(); T2pS.erase(it++)) {
// wilhelmtell in the comments is right: no need to check for NULL.
// delete of a NULL pointer is a no-op.
if(it->second != NULL) {
delete it->second;
it->second = NULL;
}
}
Run Code Online (Sandbox Code Playgroud)
对于在擦除一个迭代器时可能使其他迭代器无效的容器,erase返回下一个有效的迭代器.然后你这样做
it = T2pS.erase(it)
Run Code Online (Sandbox Code Playgroud)
这就是它是如何工作的std::vector和std::deque,而不是std::map或std::set.
在对erasea 调用迭代器后std::map,它就会失效。这意味着您无法使用它。尝试使用它(例如通过增加它)是无效的,并且可能导致任何事情发生(包括崩溃)。对于 a std::map,调用erase迭代器不会使任何其他迭代器无效,因此(例如)在此调用之后(只要itwas 不是T2pS.end()),它将有效:
T2pS.erase( it++ );
Run Code Online (Sandbox Code Playgroud)
当然,如果您使用这种方法,您不会希望it在 for 循环中无条件递增。
但对于这个例子,为什么要在 for 循环中进行擦除呢?为什么不在循环结束时调用 T2pS.clear() 呢?
另一方面,看起来您在地图的“右侧”有一个原始指针,但地图似乎拥有所指向的对象。在这种情况下,为什么不让地图右侧的东西成为某种智能指针,例如 std::tr1::shared_ptr?
[顺便说一句,我没有看到任何模板参数map。您是否在本地命名空间中typedef 了std::mapas的特定实例?]map
| 归档时间: |
|
| 查看次数: |
18558 次 |
| 最近记录: |