c++ - 为什么 std::bitset 实例中的 std::swap of Bits 不起作用?

标签 c++

在下面的示例中,我希望交换位。相反,第二位被覆盖,但为什么以及如何实现预期的行为?

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

int main()
{
    bitset<2> test(string("10"));
    cout << test; // Prints "10"
    swap(test[0], test[1]);
    cout << test; // Prints "11", why not "01"?
}

最佳答案

这纯粹是令人讨厌的。首先我们要看swap的声明:

template<class T>
void swap(T &left, T &right);

现在,bitset 上的 operator[]() 有两个重载:

bool operator[](size_type _Pos) const;
reference operator[](size_type _Pos);

这里的 referencebitset::referencebitset 中的一个嵌套类,它有效地充当了底层对象之一的代理引用位。它封装的是bitsetbitset中的一个位置。由于 swap 的声明,选择了第二个重载,我们正在交换两个 bitset::reference。现在这里是它变得讨厌的地方。让我们看一下交换的典型实现:

template class<T> swap(T &left, T &right) {
    T temp = left;
    left = right;
    right = temp;
}

问题是 leftright 都是对 bitset::reference 的引用。它们具有相同的底层数据(因为它们是代理;相同意味着两者都指向相同的 bitset!)它们只是封装了该 bitset 中的不同位置。因此,可以这样想 left 是某些 bitset 中的位置 0,right 是某些 bitset 中的位置 1并且 bitsetleft 相同 bitset!让我们永远将此 bitset 称为 BS(有意选择)。

所以,

T temp = left;

表示 tempBS 中的位置 0。

left = right;

将左边的位置 0 设置为 BS 中的位置 1(同时更改 temp 中的位置 0!)

right = temp;

将右侧的位置 1 设置为 BS 中的位置 0(刚刚设置为 BS 中的位置 1!)。所以在这个困惑的结尾,位置 0 就是位置 1 的位置,而位置 1 没有改变!现在,因为位置 0 是 LSB,位置 1 是 MSB,所以“10”变成了“11”。丑。

您可以使用 template specialization 来解决这个问题:

namespace std {
    template<>
    void swap<bitset<2>::reference>(
        bitset<2>::reference &left,
        bitset<2>::reference &right
    ) {
        bool temp = (bool)left;
        left = (bool)right;
        right = (bool)temp;
    }
}

然后:

int main() {
    bitset<2> test(string("10"));
    cout << test; // Prints "10"
    swap(test[0], test[1]);
    cout << test; // Prints "01", hallelujah!
}

关于c++ - 为什么 std::bitset 实例中的 std::swap of Bits 不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2003255/

相关文章:

c++ - 如何在没有 <array> 的情况下声明具有统一类型的元组?

c++ - 从 C++ 中的多个线程调用 Qt 中小部件类的信号函数是否安全?

c++ - Windows:UTF-16BE 到 UTF-8

C++ 部分模板特化

c++ - 如何使用 C++ 读取和解析 URL 的 XML 或 JSON 内容?

c++ - 为什么这个调用有歧义?

c++ - CryptGenRandom 输出与 rand() 调用不同

C++内存扫描

c++ - 为什么浮点异常?

c++ - 在编译器生成的复制构造函数上强制模板化构造函数