Effective STL 筆記 -- Item 9: Choose carefully among erasing options

假設有一個容器中存放着 int ,Container<int> c, 如今想從其中刪除數值 1963,能夠有以下方法:java

1: c.erase(remove(c.begin(), c.end(), 1963), c.end()); // c is continguous memory container
2: c.remove(1963); // c is list
3: c.erase(1963)   // c is standard associative container

對於 continguous memory container 來講, std::remove() 能夠保證返回的 iterator 以前的內存中不包含被刪除的值,配合 erase 來用,造成所謂的 erase-remove idiom 。而對於 List 來講,應該調用 list 自己的 remove() 方法。對於 map,set 等等,則必須使用 erase() 方法,而不能使用 remove() ,對 associative container 使用 remove() 可能會覆蓋容器存儲的內容,甚至破壞容器。c++

假設咱們如今想給定一個條件( bool badValue(int x) )並用這個條件來判斷有哪些 Entry 須要刪除,對 vector、string、deque、list 能夠用下列方法:sql

1: c.erase(remove_if(c.begin(), c.end(), badValue), c.end()); // for vector, string, deque ...
2: c.remove_if(badValue); // for list.

associative container 沒有相似的方法,但能夠自行遍歷刪除:bash

AssocContainer<int> c;
for (AssocContainer<int>::iterator i=c.begin(); i != c.end(); ++i)
{
    if (badValue(*i))
    {
        c.erase(i); //XXX: This is wrong: when this get executed, iterator will become
                    //XXX: invalid, and ++i will lead to undefined behaviour.
    }
}


for (AssocContainer<int>::iterator i=c.begin(); i != c.end(); /*Nothing*/)
{
    if (badValue(*i))
    {
        c.erase(i++); //XXX: This works, because we are passing unincreased value to erase,
                      //XXX: but we get it increased before it was passed to erase().
    }
    else
    {
        i++;
    }
}
 
相關文章
相關標籤/搜索