在下面的示例中,我希望交换位。相反,第二位被覆盖,但为什么以及如何实现预期的行为?
#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);
这里的 reference
是 bitset::reference
,bitset
中的一个嵌套类,它有效地充当了底层对象之一的代理引用位。它封装的是bitset
和bitset
中的一个位置。由于 swap
的声明,选择了第二个重载,我们正在交换两个 bitset::reference
。现在这里是它变得讨厌的地方。让我们看一下交换的典型实现:
template class<T> swap(T &left, T &right) {
T temp = left;
left = right;
right = temp;
}
问题是 left
和 right
都是对 bitset::reference
的引用。它们具有相同的底层数据(因为它们是代理;相同意味着两者都指向相同的 bitset
!)它们只是封装了该 bitset
中的不同位置。因此,可以这样想 left
是某些 bitset
中的位置 0,right
是某些 bitset
中的位置 1并且 bitset
与 left
相同 bitset
!让我们永远将此 bitset
称为 BS
(有意选择)。
所以,
T temp = left;
表示 temp
是 BS
中的位置 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/