C++ C++;快速位集短路按位操作

C++ C++;快速位集短路按位操作,c++,bitvector,C++,Bitvector,演示问题:给定两个std::bitsets,A和b检查A和b中是否都设置了位 解决这个问题有两个相当明显的办法。这是不好的,因为它创建了一个新的临时位集,并将值复制到各种位置以将其丢弃 template <size_t N> bool any_both_new_temp(const std::bitset<N>& a, const std::bitset<N>& b) { return (a & b).any(); } 有没有

演示问题:给定两个
std::bitset
s,
A
b
检查
A
b
中是否都设置了位

解决这个问题有两个相当明显的办法。这是不好的,因为它创建了一个新的临时位集,并将值复制到各种位置以将其丢弃

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_new_temp(const std::bitset<N>& a, const std::bitset<N>& b)
{
    std::bitset<N> tmp = a;
    tmp &= b;
    return tmp.any();
}
模板
bool any_two_new_temp(常量标准::位集&a,常量标准::位集&b)
{
std::位集tmp=a;
tmp&=b;
返回tmp.any();
}

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

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


教训:编写明显易读的代码,让编译器来处理。

如果不高兴,可以创建自己的类。或者最好按值传递
a
,然后直接处理它。它实际上也做了同样的事情(创建参数的副本),但如果可能的话,它会更好地启用副本省略。@ChristianRau:没错,但根据我的经验,当人们看到函数中的参数被修改时,他们往往会有一个“WTF?”时刻,即使它是通过值传递的。我记得曾经在一个C++ USENET组存档中看到一个问题,它将引用与显式复制进行比较,以使其无值传递;第一批无数的响应都(错误地)解释了传递值版本实际上是在修改对象。(我认为受访者确实了解pass-by-value和copy构造函数是如何工作的,但他们没有注意到他们期望引用的值arg。)虽然可读性的论点是可以理解的,但问题是明确的关于效率,在这种情况下,我不想错过可能的复制省略的优势。我认为,随着复制和交换习语以及类似事物的出现,获得复制习语的传递值应该在今天得到确立。
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;
}
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();
}