C++ 重载按位与运算符 operator& 详解
一、什么是按位与运算符的重载
C++ 中的 & 是一个二元运算符,默认对整数执行按位与:
cpp
int a = 0b1100;
int b = 0b1010;
int c = a & b; // 0b1000
和 +、-、| 一样,& 也可以被重载,让用户自定义类型也能用 & 运算。
cpp
class T {
public:
T operator&(const T& rhs) const {
// 返回一个新的 T
}
};
调用形式:
cpp
T x, y;
T z = x & y; // 等价于 x.operator&(y)
二、为什么按位与的重载比取地址"安全"得多
对比一元 operator&(取地址),二元 operator& 的重载要温和很多:
| 破坏语言假设 | 是(地址语义) | 否 |
| 影响标准库 | 严重 | 无 |
| 常见性 | 极少 | 较常见 |
| 推荐度 | 强烈不建议 | 视场景而定 |
二元 operator& 只是一个普通运算符重载,和 operator+ 完全对等,不会破坏语言机制。
三、典型应用场景
| 位标志 (bit flags) | Permissions、FileMode 等组合与查询 |
| 集合运算 | 用位图表示集合,& 表示交集 |
| DSL / 表达式模板 | 构建查询表达式,如 filter & condition |
| 矩阵/向量按元素与 | 数值计算库中按元素逻辑与 |
| 智能位集类 | 自定义 bitset 风格的类 |
其中位标志是最经典、最实用的场景。
#include <iostream>
#include <string>
// 权限标志(用无符号整数表示每一位)
enum class Perm : unsigned {
None = 0,
Read = 1u << 0, // 001
Write = 1u << 1, // 010
Execute = 1u << 2, // 100
};
// 权限集合类
class Permissions {
public:
// 默认构造:无权限
Permissions() : bits_(0) {}
// 从单个权限构造
Permissions(Perm p) : bits_(static_cast<unsigned>(p)) {}
// 从原始位构造(显式,避免隐式转换)
explicit Permissions(unsigned bits) : bits_(bits) {}
// ============ 重载按位与 & ============
// 语义:返回两个权限集合的"交集"
Permissions operator&(const Permissions& rhs) const {
return Permissions(bits_ & rhs.bits_);
}
// ============ 重载按位与赋值 &= ============
Permissions& operator&=(const Permissions& rhs) {
bits_ &= rhs.bits_;
return *this;
}
// ============ 顺带重载 | 和 |= ============
Permissions operator|(const Permissions& rhs) const {
return Permissions(bits_ | rhs.bits_);
}
Permissions& operator|=(const Permissions& rhs) {
bits_ |= rhs.bits_;
return *this;
}
// 转 bool:非空即可判断为 true
explicit operator bool() const { return bits_ != 0; }
// 判断是否包含某个权限
bool has(Perm p) const {
return (bits_ & static_cast<unsigned>(p)) != 0;
}
unsigned raw() const { return bits_; }
private:
unsigned bits_;
};
// 让 `Permissions & Perm` 也能用(对称性)
inline Permissions operator&(Permissions lhs, Perm rhs) {
return lhs & Permissions(rhs);
}
int main() {
// 组合:Read | Write
Permissions rw = Permissions(Perm::Read) | Permissions(Perm::Write);
std::cout << "rw.bits = " << rw.raw() << "\\n"; // 3
// 1) 用 & 求交集:rw & Read
Permissions onlyRead = rw & Permissions(Perm::Read);
std::cout << "onlyRead.raw = " << onlyRead.raw() << "\\n"; // 1
// 2) 用 if (p & mask) 做权限检查
if (rw & Permissions(Perm::Read)) {
std::cout << "有读权限\\n";
}
if (!(rw & Permissions(Perm::Execute))) {
std::cout << "没有执行权限\\n";
}
// 3) 用 has() 更直观
std::cout << "has(Write)? " << rw.has(Perm::Write) << "\\n"; // 1
std::cout << "has(Execute)? " << rw.has(Perm::Execute) << "\\n"; // 0
// 4) 用 &= 原地取交集
Permissions p = Permissions(Perm::Read) | Permissions(Perm::Write);
p &= Permissions(Perm::Read);
std::cout << "p.raw = " << p.raw() << "\\n"; // 1
return 0;
}





