【问题标题】:Is there a programming standard about algorithms such as erase/remove_if and possible side effects of the remove_if implementation?是否有关于诸如擦除/remove_if 等算法的编程标准以及 remove_if 实现的可能副作用?
【发布时间】:2018-01-18 18:14:20
【问题描述】:

我有一个弱指针向量,如果指针仍然存在,我想遍历该列表并执行一个函数。如果指针消失了,我想将其移除。

class my_class
{
public:
    std::shared_ptr<my_class>    pointer_t;
    std::weak_ptr<my_class>      weak_pointer_t;
    ...

private:
    ...
};

class listeners_class
{
public:
    typedef std::vector<my_class::weak_ptr>  listeners_t;
    ...

private:
    listeners_t    f_listeners;
    ...
};

我注意到我可以直接在remove_if() 测试函数中实现它,因为remove_if() 实际上循环遍历整个向量并尝试锁定弱指针。另外,这种方式更原子

有 lambda 的代码。

    f_listeners.erase(
        std::remove_if(
              f_listeners.begin()
            , f_listeners.end()
            , [&ptr](my_class::weak_pointer_t l)
            {
                my_class::pointer_t ll(l.lock());
                if(ll == nullptr)
                {
                    return true;
                }
                ll->some_callback(ptr);  // <<-- side effect!
                return false;
            })
        );

我认为这是不好的做法,但想确认是否有关于此类代码的标准形式。

【问题讨论】:

  • 这里的目标是删除失去目标的弱指针吗?
  • 是的。两个目标:如果指针仍然存在,则调用some_callback(),否则从向量中删除指针。
  • 我认为这里的一般期望是只要您不直接修改您正在迭代的容器,这会使迭代器无效,并且some_callback 不使用ptr在立即同步块之外,那么你应该没问题。这里有很多警告。
  • 如果我写它,我会通过两次。第一遍(上图)删除了所有“过期”的弱指针。第二遍调用所有剩余的some_callback(可以使用for_each完成)
  • @MarshallClow 这个问题的重点似乎是避免两次通过。但是,可能必须证明它有所作为

标签: c++ language-lawyer stl-algorithm side-effects


【解决方案1】:

标准没有具体说明实现。但是,我们可以从标准中得出,只要您不关心每个元素的预测函数的评估顺序,您的代码就会按预期工作。

首先,[alg.remove]

效果: 消除迭代器 i 在范围 [first, last) 中引用的所有元素,并满足以下相应条件:*i == value, pred(*i) != false .

...

复杂性:正好last - first应用相应的谓词。

这些约束保证预测函数对每个元素只执行一次

第二,[res.on.data.races]/8

除非另有说明,否则 C++ 标准库函数应仅在当前线程内执行所有操作,前提是这些操作具有用户可见的效果。

关于the comment in [intro.execution]/11

换句话说,函数执行不会相互交错。

所以你可以在某种意义上考虑预测函数的原子执行。

【讨论】:

    猜你喜欢
    • 2017-06-26
    • 2012-02-21
    • 2010-10-22
    • 1970-01-01
    • 1970-01-01
    • 2021-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多