C++赋值运算符 #
一、基本赋值运算符 #
1.1 基本用法 #
cpp
// 基本赋值
int x = 10;
double d = 3.14;
char c = 'A';
1.2 赋值表达式 #
赋值运算符返回左值的引用。
cpp
int x;
int y = (x = 10); // x = 10, y = 10
// 链式赋值
int a, b, c;
a = b = c = 0; // 从右向左赋值
1.3 赋值与初始化 #
cpp
// 初始化
int x = 10; // 调用拷贝构造函数
// 赋值
int y;
y = 10; // 调用赋值运算符
二、复合赋值运算符 #
2.1 运算符列表 #
| 运算符 | 等价形式 | 示例 |
|---|---|---|
+= |
a = a + b |
x += 5 |
-= |
a = a - b |
x -= 5 |
*= |
a = a * b |
x *= 5 |
/= |
a = a / b |
x /= 5 |
%= |
a = a % b |
x %= 5 |
&= |
a = a & b |
x &= 5 |
|= |
a = a | b |
x |= 5 |
^= |
a = a ^ b |
x ^= 5 |
<<= |
a = a << b |
x <<= 2 |
>>= |
a = a >> b |
x >>= 2 |
2.2 基本使用 #
cpp
int x = 10;
x += 5; // x = 15
x -= 3; // x = 12
x *= 2; // x = 24
x /= 4; // x = 6
x %= 4; // x = 2
2.3 位运算复合赋值 #
cpp
int flags = 0b1010;
flags |= 0b0101; // flags = 0b1111 (15)
flags &= 0b1100; // flags = 0b1100 (12)
flags ^= 0b1000; // flags = 0b0100 (4)
flags <<= 2; // flags = 0b10000 (16)
flags >>= 1; // flags = 0b01000 (8)
三、复合赋值 vs 普通赋值 #
3.1 效率差异 #
cpp
// 复合赋值:更高效
array[index] += value; // 只计算一次array[index]
// 普通赋值:可能计算两次
array[index] = array[index] + value; // array[index]计算两次
3.2 复杂表达式 #
cpp
// 复合赋值更清晰
getValue().data[index] += 1;
// 普通赋值冗长
getValue().data[index] = getValue().data[index] + 1;
四、自增自减与赋值 #
4.1 与复合赋值的区别 #
cpp
int x = 5;
// 自增:只能加1
x++; // x = 6
// 复合赋值:可以加任意值
x += 5; // x = 11
4.2 使用场景 #
cpp
// 自增:循环计数
for (int i = 0; i < 10; i++) {
// ...
}
// 复合赋值:累加
int sum = 0;
for (int i = 1; i <= 10; i++) {
sum += i; // 累加
}
五、赋值运算符优先级 #
5.1 优先级很低 #
cpp
// 赋值运算符优先级很低,几乎最后执行
int x = 5 + 3 * 2; // x = 11
// 赋值在条件表达式中
int y;
if ((y = getValue()) > 0) { // 先赋值,再比较
// ...
}
5.2 结合性 #
cpp
// 赋值运算符从右向左结合
int a, b, c;
a = b = c = 10; // c = 10, b = c, a = b
5.3 注意事项 #
cpp
// 危险:赋值在条件中
int x;
if (x = 5) { // x被赋值为5,条件为true
// ...
}
// 正确:使用比较
if (x == 5) {
// ...
}
// 或者使用括号强调
if ((x = getValue()) != 0) {
// ...
}
六、赋值与类型转换 #
6.1 隐式类型转换 #
cpp
double d = 3.14;
int i = d; // 隐式转换,i = 3
// 复合赋值也会转换
int x = 10;
x += 3.5; // x = 13(3.5被截断为3)
6.2 窄化转换警告 #
cpp
double d = 3.14;
// 可能警告
int i = d;
// 显式转换消除警告
int i = static_cast<int>(d);
七、自定义赋值运算符 #
7.1 拷贝赋值运算符 #
cpp
class String {
private:
char* data;
size_t length;
public:
// 拷贝赋值运算符
String& operator=(const String& other) {
if (this != &other) { // 自赋值检查
delete[] data;
length = other.length;
data = new char[length + 1];
strcpy(data, other.data);
}
return *this;
}
};
7.2 移动赋值运算符(C++11) #
cpp
class String {
public:
// 移动赋值运算符
String& operator=(String&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
length = other.length;
other.data = nullptr;
other.length = 0;
}
return *this;
}
};
7.3 复合赋值运算符 #
cpp
class Complex {
public:
double real, imag;
Complex& operator+=(const Complex& other) {
real += other.real;
imag += other.imag;
return *this;
}
Complex& operator-=(const Complex& other) {
real -= other.real;
imag -= other.imag;
return *this;
}
};
八、实际应用 #
8.1 累加器 #
cpp
int sum = 0;
int product = 1;
for (int i = 1; i <= 10; i++) {
sum += i; // 累加
product *= i; // 累乘
}
8.2 标志操作 #
cpp
int flags = 0;
// 设置标志
flags |= FLAG_A;
flags |= FLAG_B;
// 清除标志
flags &= ~FLAG_A;
// 切换标志
flags ^= FLAG_C;
8.3 字符串拼接 #
cpp
#include <string>
std::string result = "Hello";
result += ", ";
result += "World";
result += "!"; // "Hello, World!"
8.4 容器操作 #
cpp
#include <vector>
std::vector<int> vec;
vec = {1, 2, 3}; // 赋值
std::vector<int> vec2;
vec2 = std::move(vec); // 移动赋值
九、最佳实践 #
9.1 优先使用复合赋值 #
cpp
// 推荐
x += 1;
arr[i] *= 2;
// 不推荐
x = x + 1;
arr[i] = arr[i] * 2;
9.2 注意赋值与比较的区别 #
cpp
// 错误
if (x = 5) { }
// 正确
if (x == 5) { }
// 如果确实需要赋值后判断
if ((x = getValue()) > 0) { }
9.3 避免自赋值 #
cpp
class MyClass {
public:
MyClass& operator=(const MyClass& other) {
if (this != &other) { // 检查自赋值
// 执行赋值操作
}
return *this;
}
};
9.4 使用移动语义 #
cpp
std::vector<int> vec1 = {1, 2, 3};
std::vector<int> vec2;
// 移动赋值,避免拷贝
vec2 = std::move(vec1);
十、总结 #
赋值运算符一览 #
| 运算符 | 说明 | 示例 |
|---|---|---|
= |
赋值 | x = 10 |
+= |
加赋值 | x += 5 |
-= |
减赋值 | x -= 5 |
*= |
乘赋值 | x *= 5 |
/= |
除赋值 | x /= 5 |
%= |
取余赋值 | x %= 5 |
&= |
位与赋值 | x &= 5 |
|= |
位或赋值 | x |= 5 |
^= |
异或赋值 | x ^= 5 |
<<= |
左移赋值 | x <<= 2 |
>>= |
右移赋值 | x >>= 2 |
注意事项 #
- 区分
=和== - 优先使用复合赋值
- 注意自赋值问题
- 理解赋值表达式的返回值
- 注意类型转换
下一步,让我们学习运算符优先级!
最后更新:2026-03-26