【问题标题】:C++ Fast Bitset Short-Circuit Bitwise OperationsC++ 快速位集短路按位运算
【发布时间】:2011-12-02 00:24:49
【问题描述】:

一个演示问题:给定两个std::bitset<N>s、ab,检查ab 中是否设置了任何位。

这个问题有两个相当明显的解决方案。这很糟糕,因为它创建了一个新的临时位集,并将值复制到各种地方,只是为了扔掉它们。

template <size_t N>
bool any_both_new_temp(const std::bitset<N>& a, const std::bitset<N>& b)
{
    return (a & b).any();
}

这个解决方案很糟糕,因为它一次只运行一点,不太理想:

template <size_t N>
bool any_both_bit_by_bit(const std::bitset<N>& a, const std::bitset<N>& b)
{
    for (size_t i = 0; i < N; ++i)
        if (a[i] && b[i])
            return true;
    return false;
}

理想情况下,我可以做这样的事情,其中​​block_typeuint32_tbitset 存储的任何类型:

template <size_t N>
bool any_both_by_block(const std::bitset<N>& a, const std::bitset<N>& b)
{
    typedef std::bitset<N>::block_type block_type;
    for (size_t i = 0; i < a.block_count(); ++i)
        if (a.get_block(i) & b.get_block(i))
            return true;
    return false;
}

有没有简单的方法来做到这一点?

【问题讨论】:

  • 如果您不满意,请创建自己的课程。

标签: c++ bitvector


【解决方案1】:

我在g++ 中使用优化编译了您的第一个示例,它生成的代码与您的第三个解决方案相同。事实上,使用较小的位集(320 位),它完全展开了它。没有调用函数来确保ab 的内容在main 中是未知的,它实际上优化了整个事情(知道两者都是0)。

课程:编写明显、可读的代码,然后让编译器处理。

【讨论】:

    【解决方案2】:

    您说您的第一种方法“复制各种地方的值只是为了扔掉它们。”但是实际上只有一个额外的值副本(当operator&amp;的结果返回到any_both_new_temp时),可以通过使用引用而不是值来消除:

    template <size_t N>
    bool any_both_new_temp(const std::bitset<N>& a, const std::bitset<N>& b)
    {
        std::bitset<N> tmp = a;
        tmp &= b;
        return tmp.any();
    }
    

    (但显然它仍然会创建一个临时的bitset 并将a 复制到其中。)

    【讨论】:

    • 或者最好通过值传递a 并直接处理它。它实际上做了同样的事情(创建参数的副本),但如果可能的话,它更好地启用复制省略。
    • @ChristianRau:确实如此,但根据我的经验,人们往往会有“WTF?”当他们看到一个参数在函数中被修改时,即使它是按值传递的。我记得曾经在 C++ Usenet-group 存档中看到过一个问题,该问题将 pass-by-reference-with-explicit-copy 与 pass-by-value-without-it 进行了比较;最初的大量响应都(错误地)解释说,传值版本实际上是在修改对象。 (我认为受访者确实了解 pass-by-value 和 copy-constructors 的工作原理,但他们没有注意到他们期望 ref 的值 arg。)
    • 虽然可读性参数是可以理解的,但问题是明确的效率问题,在这种情况下,我不想错过可能的复制省略的优势。而且我认为随着复制和交换习语和类似事物的出现,现在应该已经建立了按值传递以获取副本的习语。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-26
    • 2020-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多