迭代器有效性,在 std::set 中调用擦除()之后

发布于 2024-08-09 00:12:44 字数 781 浏览 3 评论 0原文

std::set 中的擦除调用会使迭代器无效吗?正如我从最后一行开始的第 5 行以下所做的那样……? 如果是的话,从集合中删除所有元素的更好方法是什么

class classA
{
public:
    classA(){};
    ~classA(){};
};
struct structB
{
};

typedef std::set <classA*, structB> SETTYPE;        
typedef std::map <int, SETTYPE>MAPTYPE;

int __cdecl wmain (int argc, wchar_t* pArgs[])
{
    MAPTYPE mapObj; 
    /*
      ...
      ..   Some Operation Here
      ...
      */
    for (MAPTYPE::iterator itr1=mapObj.begin(); itr1!=mapObj.end(); itr1++) 
    {       
        SETTYPE li=(*itr1).second;
        for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();itr2++) 
        {
            classA *lt=(classA*)(*itr2);
            li.erase(itr2); 
            delete lt; // Does it invalidate Iterator ?
        }
    }
}

Do erase call in std::set invalidate iterator ? As i have done below 5th from last line..?
if yes what is better way to erase all elements from set

class classA
{
public:
    classA(){};
    ~classA(){};
};
struct structB
{
};

typedef std::set <classA*, structB> SETTYPE;        
typedef std::map <int, SETTYPE>MAPTYPE;

int __cdecl wmain (int argc, wchar_t* pArgs[])
{
    MAPTYPE mapObj; 
    /*
      ...
      ..   Some Operation Here
      ...
      */
    for (MAPTYPE::iterator itr1=mapObj.begin(); itr1!=mapObj.end(); itr1++) 
    {       
        SETTYPE li=(*itr1).second;
        for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();itr2++) 
        {
            classA *lt=(classA*)(*itr2);
            li.erase(itr2); 
            delete lt; // Does it invalidate Iterator ?
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

三生一梦 2024-08-16 00:12:44

来自标准 23.1.2

插入成员不应影响迭代器和对容器的引用的有效性,而擦除成员应仅使迭代器和对已擦除元素的引用无效。

编辑

在您的情况下 itr2 在擦除后无效,因此增加它会导致未定义的行为。在这种情况下,您可以遵循 reko_t 建议,一般来说,您可以尝试以下操作:

for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();) 
{
    classA *lt=(classA*)(*itr2);
    li.erase(itr2++); 
    delete lt;
}

这将在之前从集合中删除其先前的值之前增加迭代器。
顺便提一句。 itr2 不会被 delete lt; 失效,而是被 li.erase(itr2); 失效

From standard 23.1.2

The insert members shall not affect the validity of iterators and references to the container, and the erase members shall invalidate only iterators and references to the erased elements.

EDIT

In your case itr2 is invalidated after erasing so incrementing it causes undefined behaviour. In this case you can follow reko_t advice, in general, you can try this:

for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();) 
{
    classA *lt=(classA*)(*itr2);
    li.erase(itr2++); 
    delete lt;
}

which will increment iterator before removing it's previous value from set.
BTW. itr2 is not invalidated by delete lt;, but by li.erase(itr2);

计㈡愣 2024-08-16 00:12:44

删除就ok了

问题是您擦除了 - 从而使 - itr2 无效,但将其用于循环迭代。

iaw 第一次擦除后,++itr2 具有未定义的结果。

我在这种情况下使用的模式是这样的:

while(itr2 != end())
{
   iterator toDelete = itr2;
   ++itr2;   // increment before erasing!
   container.erase(toDelete);
}

一些非标准 STL impls 已擦除返回下一个迭代器,因此您可以这样做:

while(itr2 != end())
   itr2 = container.erase();

但这不是可移植的。


set 很奇怪,尽管在标准实现中,B 将是比较器。

The delete is ok.

The problem is that you erase - and thus invalidate - itr2, but use it for loop iteration.

i.a.w. after the first erase, the ++itr2 has undefined results.

The pattern I use in this situation is this:

while(itr2 != end())
{
   iterator toDelete = itr2;
   ++itr2;   // increment before erasing!
   container.erase(toDelete);
}

Some non-standard STL impls have erase return the next iterator, so you could do:

while(itr2 != end())
   itr2 = container.erase();

that's not portable, though.


the set<A*,B> is strange, though - in a standard impl, B would be the comparator.

一曲琵琶半遮面シ 2024-08-16 00:12:44

由于您显然只是删除了集合中的每个元素,因此您可以这样做:

    for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();itr2++) 
    {
            classA *lt=(classA*)(*itr2);
            delete lt;
    }
    li.clear(); // clear the elements

Since you are just apparently deleting every element of the set, you could just do:

    for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();itr2++) 
    {
            classA *lt=(classA*)(*itr2);
            delete lt;
    }
    li.clear(); // clear the elements
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文