about wxVector Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
dqf88
Experienced Solver
Experienced Solver
Posts: 55
Joined: Fri Aug 10, 2012 9:59 am

about wxVector

Post by dqf88 » Sat Nov 17, 2018 1:44 pm

what's wrong with the following code?

Code: Select all

struct Line
{
    wxPoint ptStart;
    wxPoint ptEnd;
    bool isSelected;
} ;

wxVector<Line> lines;

Line l;
l.ptStart=wxPoint(20,30);
l.ptEnd=wxPoint(270,390);
l.isSelected=true;
lines.push_back(l);

wxVector<Line>::iterator i;
for(i=lines.begin(); i!=lines.end(); i++)
{
    cout<<(*i).isSelected<<endl;
    if((*i).isSelected)
    {
        lines.erase(i);
    }
}
Attachments
1.png
1.png (40.79 KiB) Viewed 703 times

User avatar
T-Rex
Moderator
Moderator
Posts: 1182
Joined: Sat Oct 23, 2004 9:58 am
Location: Zaporizhzhya, Ukraine
Contact:

Re: about wxVector

Post by T-Rex » Sat Nov 17, 2018 2:04 pm

This is because it's not permitted to erase the iterator inside the loop if this iterator is used as loop's parameter.
You should iterate by index then or re-assign the value of `i` while erasing.

Just Google for the relevant example.
https://stackoverflow.com/questions/596 ... through-it

dqf88
Experienced Solver
Experienced Solver
Posts: 55
Joined: Fri Aug 10, 2012 9:59 am

Re: about wxVector

Post by dqf88 » Sat Nov 17, 2018 3:09 pm

Code: Select all

wxVector<Line>::iterator i;
for(i=lines.begin(); i!=lines.end();)
{
    if((*i).isSelected)
    {
        i=lines.erase(i);
    }
    else
    {
        i++;
    }
}

dqf88
Experienced Solver
Experienced Solver
Posts: 55
Joined: Fri Aug 10, 2012 9:59 am

Re: about wxVector

Post by dqf88 » Sat Nov 17, 2018 3:11 pm

for循环中调用vector容器erase函数

代码示例

Code: Select all

int main(){  
    vector<int> a;  
    a.push_back(3);  
    a.push_back(2);  
    a.push_back(3);  
    a.push_back(3);  
    a.push_back(5);  
    vector<int>::iterator b;  
    int x = 3;  
    for(b=a.begin();b!=a.end();b++)  
    {  
        if(*b==x){  
            b=a.erase(b);  
        }  
    }  
    for(b=a.begin();b!=a.end();b++)  
    {  
        printf("value=%d\n", *b);  
    }  
    return 0;  
}  


现象&后果

上面代码的目的是,使用迭代器循环删除vector中所有的3,但你会发现并不是所有的3都被删除掉了。

Bug分析

上述代码主要问题是对容器类vector的erase函数理解不够。代码中调用的erase函数在删除当前元素b后,返回b后面的元素。在上述代码的vector中,一开始有3个3,其中后两个3是连续的,在删除第二个3之后,erase函数返回的下一个元素还是3,然而代码运行到循环的b++时,就略过了这个3,从而造成不是所有的3都被删除。

正确的做法是,在删除元素的之后,由于erase函数已经自动跳到下一个元素,跳过接下来循环的b++语句。

正确代码

Code: Select all

int main(){  
    vector<int> a;  
    a.push_back(3);  
    a.push_back(2);  
    a.push_back(3);  
    a.push_back(3);  
    a.push_back(5);  
    vector<int>::iterator b;  
    int x = 3;  
    for(b=a.begin();b!=a.end();)  
    {  
        if(*b==x){  
            b=a.erase(b);  
        }else{  
            b++;  
        }  
    }  
    for(b=a.begin();b!=a.end();b++)  
    {  
        printf("value=%d\n", *b);  
    }  
    return 0;  
}
编程建议

在对容器类元素进行增、删操作时,一定要注意增、删操作的返回值和迭代器指示器是否发生变化,必要的时候需要进行修正。

Post Reply