位操作- c++中对结构体和类的按位操作
bit manipulation - C++ bitwise operations on structs and classes
我正在开发一个通用遗传算法库,其中每个生物体的染色体是它在内存中的位表示。例如,如果我想让一个有机体发生突变,我就随机地翻转这个物体的比特。
首先,我尝试使用来自c++标准库的bitset
类,但是,当转换回对象T
时,我唯一的选择是使用to_ullong
成员函数,这对于表示大于unsigned long long
大小的位数是一个问题。
然后我决定为任何对象T
上的按位操作创建一个通用库,这样我就可以直接将这些操作应用到对象本身,而不是先将它们转换为bitset
。
所以你可以看到我想要实现的,这是一个来自库的函数:
template<typename T>
void flip(T& x, size_t const i)
{
x ^= 1 << i;
}
它在GA库中是这样使用的:
template<typename T>
void GeneticAlgorithm<T>::mutate(T& organism, double const rate)
{
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_real_distribution<double> dist(0, 1);
for(size_t i = 0; i < m_nBits; ++i)
if(dist(mt) <= rate)
bit::flip(organism, i);
}
这将是非常好的,如果这工作,但现在我得到这个错误消息从vc++ 2015 RC编译器:
严重性代码描述项目文件行错误C2677二进制'^':no找到接受类型为'T'的全局操作符(否则不接受) GeneticAlgorithm GeneticAlgorithm BitManip.hpp 57
如果我纠正^
的这个错误,我得到更多的其他操作符。
我没有使用位操作符之前在我的代码,所以我猜这些操作符不应该与任何对象使用?如果是这样,我该如何解决这个问题?
你想要达到的效果可以这样做(参见Peter Schneider的评论):
template<typename T> void flip(T& x, size_t const i) {
unsigned char* data = reinterpret_cast<unsigned char*>(&x);
data[i/8] ^= (1 << (i%8));
}
它所做的是将数据x重新解释为字节数组(unsigned char),然后确定应该翻转哪个字节(i/8),然后在字节内的哪个位(i%8)。
注意:另外,在函数的开头添加: 也是安全的。assert(i < sizeof(T)*8)
我的印象是您还没有完全理解c++提供的面向对象特性。(这在C语言中以数据为中心的编程中并不少见。c++是专门设计来以期望的速度实现这种转换的,并且使其无痛。)
我的建议是将翻转操作封装在一个有机体中,让有机体来处理它。举个例子(未经测试,但可以编译):
#include<climits> // CHAR_BIT
#include<cstdlib> // exit()
class string;
void log(const char *);
// inaccessible from the outside
constexpr int NUM_TRAITS = 1000;
constexpr size_t TRAIT_ARR_SZ = (NUM_TRAITS+CHAR_BIT-1)/CHAR_BIT;
class Organism
{
char traits[TRAIT_ARR_SZ];
int flips[NUM_TRAITS];
/////////////////////////////////////////////////////////////
public:
Organism() { /* set traits and flips zero */ }
// Consider a virtual function if you may derive
/** Invert the trait at index traitIndex */
void flipTrait(int traitIndex)
{
if( traitIndex >= NUM_TRAITS ) { log("trait overflow"); exit(1); }
int charInd = traitIndex / CHAR_BIT;
int bitInd = traitIndex % CHAR_BIT;
traits[traitIndex] ^= 1 << bitInd;
flips[traitIndex]++;
}
// Organisms can do so much more!
void display();
void store(string &path);
void load(string &path);
void mutate(float traitRatio);
Organism clone();
};
- 对字符串进行位操作
- 对字符数组中的元素执行逐位操作
- 逐位操作的隐式类型转换
- 如何进行特定的位操作?
- C++避免位操作完全移位
- 使用双包装器类进行位操作(C++、clang)修复性能下降问题
- 使用位操作优化检查
- 子集相关位操作
- 使用 c++ 提升库的按位操作
- 位操作和异或
- 位操作将最左侧的设置位转换为右侧交替位?
- 为什么对小于 4 个字节的整数类型的位操作会发生意外行为?
- POD 类型的原子按位操作
- 如何使用位操作在单个整数中编码和解码两个数字
- __int128的位操作
- 使用位操作会影响内存消耗?
- 在具有位操作的函数中获得值
- C/C 位操作不会导致预期输出
- 在数组大小中使用位操作的原因
- 了解C++位操作中的二进制转换实现