c++ - vector 迭代和删除

标签 c++ vector iterator iteration

我正在编写多线程 C++ WIN 套接字服务器,我遇到了一些奇怪的问题。

我正在使用 vector 来存储事件连接。我用 win mutex 锁定 vector ,然后我尝试遍历它以找到所有关闭的连接并删除它们,然后释放互斥量。

代码:

if (!m_activeConnections.empty()){
    for(std::vector<Connection*>::iterator it = m_activeConnections.begin(); it != m_activeConnections.end(); ++it) {
        if ((*it)->isClosed()){
            delete *it;
            it = m_activeConnections.erase(it);
            break;
        }
    }
    cout << "\n \t Active Connections: " << m_activeConnections.size() << endl;
}

它是这样工作的,但是当我删除 break 行时,它总是再循环一次,迭代器 it 指向 0Xaaaaaa 并抛出异常。如果此删除是在创建新连接的同一线程中完成的,即使没有中断,它也能正常工作。这是为什么?

最佳答案

无论何时修改范围,都必须确保以与从范围中删除时使迭代器失效的方式兼容的方式更新用于遍历范围的迭代器。

将此方法应用于 vector 的一个简单示例是以下循环。请注意,删除会使从删除点开始的所有迭代器失效,因此您需要在删除时获取新的迭代器,并且还需要重新计算 end()。每次(即不要将结束计算提升到循环之外):

for (auto it = m_activeConnections.begin(); it != m_activeConnections.end(); )
{
    if ((*it)->isClosed()) { it = m_activeConnections.erase(it); }
    else                   { ++it;                               }
}

从 vector 中删除的更好方法是将要删除的元素移动到 vector 的后面,然后一次删除整个范围,避免一直移动尾部范围。通常我们用 remove_if 来做到这一点,虽然你需要添加一些技巧来删除你的案例中的指针:

m_activeConnections.erase(
    std::remove_if(m_activeConnections.begin(),
                   m_activeConnections.end(),
                   [](Connection * p) {
                      if (p->isClosed()) { delete p; return true; }
                      return false;}),
    m_activeConnections.end());

如果将容器更改为 std::vector<std::unique_ptr<Connection>>,就可以避免这种欺骗行为: 每个职责都有一个类( vector 包含,唯一指针删除),算法变得可组合。

如果你不能通过选择适当的抽象来让你的代码变得简单,你也可以尝试更复杂的算法:先根据需要划分范围删除,然后删除,然后删除范围:

auto it = std::stable_partition(m_activeConnections.begin(),
                                m_activeConnections.end(),
                                [](Connection * p) { return p->isClosed(); });

for (auto kt = it; kt != m_activeConnections.end(); ++kt)
{
    delete *kt;
}

m_activeConnections.erase(it, m_activeConnections.end());

关于c++ - vector 迭代和删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29402841/

相关文章:

c++ - 是否为 n 创建了单独的内存位置,或者 m 或 n 都指向同一位置?

c++ - 为什么我不需要将取消引用运算符与 map 的 .at() 方法一起使用?

c++ - 超过时限

arrays - 使用迭代器而不是 Swift 中的位置访问数组的元素

c++ - 在链表上实现随机访问迭代器

c++ - 安全转换为 const char * - 临时生命周期问题

c++ - 从零开始的 Lua/C++ 绑定(bind)

c++ - 从 vector 中删除项目,而在 C++11 范围 'for' 循环中?

loops - 如何编写传递给函数的迭代器类型?

c++ - std::vector的迭代器分类