C ++ remove_if没有迭代整个向量

时间:2016-12-20 19:46:17

标签: c++ vector iterator remove-if

我有一个指针向量,指向大约10MB的数据包。在那,从前2MB,我想删除所有匹配我的谓词。这里的问题是remove_if遍历整个向量,即使在我的用例中不需要它。还有其他有效的方法吗?

fn_del_first_2MB
{
    uint32 deletedSoFar = 0;
    uint32 deleteLimit = 2000000;

    auto it = std::remove_if (cache_vector.begin(), cache_vector.end(),[deleteLimit,&deletedSoFar](const rc_vector& item){
    if(item.ptr_rc->ref_count <= 0) {
        if (deletedSoFar < deleteLimit) {
            deletedSoFar += item.ptr_rc->u16packet_size;
        delete(item.ptr_rc->packet);    
        delete(item.ptr_rc);
            return true;
        }
        else    
            return false;
    }
    else
        return false;
    });
    cache_vector.erase(it, cache_vector.end());
}

在上面的代码中,一旦deletedSoFar大于deleteLimit,任何超过该值的迭代都是不需要的。

3 个答案:

答案 0 :(得分:3)

而不是cache_vector.end()放置您自己的迭代器标记myIter。使用remove_if选项,您应该遵循erase-remove惯用法。以下是仅影响前4个元素的示例:

#include <iostream>
#include <vector>
#include <algorithm>

int main()
{
    std::vector<int> vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    size_t index = 4; // index is something you need to calculate
    auto myIter = vec.begin() + index; // Your iterator instead of vec.end()
    vec.erase(std::remove_if(vec.begin(), myIter, [](int x){return x < 3; }), myIter);
    // modified vector:
    for (const auto& a : vec)
    {
        std::cout << a << std::endl;
    }
    return 0;
}

答案 1 :(得分:1)

std::remove_if()不需要将.end()迭代器作为第二个参数传递:只要第一个参数可以通过递增到达第二个参数,就可以传递任何迭代器。

由于您的条件取决于到目前为止所遇到的元素的累积大小,因此存在一些复杂情况。事实证明,看起来好像不会使用std::remove_if()。这样的事情应该有用(虽然我不确定std::find_if()的使用是否真的合法,因为它不断改变谓词):

std::size_t accumulated_size(0u);
auto send(std::find_if(cache_vector.begin(), cache_vector.end(),
                              [&](rc_vector const& item) {
        bool rc(accumulated_size < delete_limit);
        accumulated_size += item.ptr_rc->u16packet_size;
        return rc;
    });
std::for_each(cache_vector.begin(), send, [](rc_vector& item) {
       delete(item.ptr_rc->packet);    
       delete(item.ptr_rc);
    });
cache_vector.erase(cache_vector.begin(), send);

std::for_each()也可以折叠成std::find_if()的使用,但我更喜欢将逻辑分开。对于足够大的序列,当存储器需要两次传输到高速缓存时可能存在性能差异。对于引用的微小数字,我怀疑可以衡量差异。

答案 2 :(得分:1)

您可以使用自己的循环:

void fn_del_first_2MB()
{
    const uint32 deleteLimit = 2000000;

    uint32 deletedSoFar = 0;
    auto dest = cache_vector.begin();
    auto it = dest

    for (; it != cache_vector.end(); ++it) {
        const auto& item = *it;

        if (item.ptr_rc->ref_count <= 0) {
            deletedSoFar += item.ptr_rc->u16packet_size;
            delete(item.ptr_rc->packet);    
            delete(item.ptr_rc);
            if (deletedSoFar >= deleteLimit) {
                ++it;
                break;
            }
        } else if (dest != it) {
            *dest = std::move(*it);
            ++dest;
        }
    }
    cache_vector.erase(dest, it);
}