算术运算符

C++ 中的算术运算符是对基本数据类型进行数学运算的核心工具。包括加、减、乘、除、取模、递增/递减等操作。它们适用于内置类型,也可以通过重载应用于用户自定义类型(如类/结构体)。


1. 算术运算符一览表

运算符 含义 示例 支持类型
+ 加法 a + b 数值/指针(偏移)
- 减法 a - b 数值/指针差
* 乘法 a * b 数值
/ 除法 a / b 数值(注意除以 0)
% 取模(余数) a % b 整数类型(不可用于浮点)
++ 自增(前/后) ++a, a++ 整型、指针等
-- 自减(前/后) --a, a-- 整型、指针等
- 一元负号 -a 数值
+ 一元正号 +a 数值

2. 示例代码(基础类型)

#include <iostream>
using namespace std;

int main() {
    int a = 10, b = 3;

    cout << "a + b = " << a + b << endl;
    cout << "a - b = " << a - b << endl;
    cout << "a * b = " << a * b << endl;
    cout << "a / b = " << a / b << endl;     // 整数除法
    cout << "a % b = " << a % b << endl;     // 取模

    float x = 5.0f, y = 2.0f;
    cout << "x / y = " << x / y << endl;     // 浮点除法

    return 0;
}

3. 自增与自减(前置与后置)

int a = 5;
int b = ++a;   // a=6, b=6(前置先加再赋值)
int c = a++;   // a=7, c=6(后置先赋再加)

4. 算术运算符重载示例(复数类)

#include <iostream>
class Complex {
public:
    double r, i;

    Complex(double real, double imag) : r(real), i(imag) {}

    // 重载加法
    Complex operator+(const Complex& other) const {
        return Complex(r + other.r, i + other.i);
    }

    // 重载乘法
    Complex operator*(const Complex& other) const {
        return Complex(r * other.r - i * other.i, r * other.i + i * other.r);
    }

    void print() const {
        std::cout << r << " + " << i << "i" << std::endl;
    }
};

int main() {
    Complex a(2, 3), b(4, -1);
    Complex c = a + b;
    Complex d = a * b;

    c.print();  // 输出:6 + 2i
    d.print();  // 输出:11 + 10i

    return 0;
}

5. 运算符优先级(部分)

优先级(高 → 低) 运算符 说明
1 ++, --, +, - 一元运算
2 *, /, % 乘除取模
3 +, - 加减
4 赋值类 =, +=, -= 赋值

可参考 C++ 运算符优先级表


6. 特殊注意事项

  • 除法注意整数除法截断:

    int a = 5, b = 2;
    cout << a / b << endl;  // 输出 2(截断小数)
    
  • 取模只适用于整数。

  • 浮点精度误差:

    double x = 0.1 + 0.2;
    cout << x << endl;  // 输出可能不是 0.3,而是 0.300000...
    

7. 总结

操作符 用途 是否可重载 注意点
+ - * / % 基本算术 % 不适用浮点
++ -- 自增自减 前后置行为不同
+ - 一元 正负号 可用作符号切换
重载 用户类型支持 建议 const 成员,支持链式调用

C++ 算术运算符重载最佳实践

在 C++ 中,算术运算符重载允许用户让自定义类型(如复数、向量、矩阵、货币金额等)使用自然的数学符号(如 +, -, *, /)进行运算,就像内置类型一样。这提升了代码的可读性和可维护性,但也容易引入设计失误。


一、常见可重载的算术运算符

运算符 常用含义
+ 加法
- 减法
* 乘法(标量乘法 / 点积 / 矩阵乘法)
/ 除法(标量除法)
% 模运算(一般不用重载)
+= 自加
-= 自减
*= 自乘
/= 自除

二、重载方式选项:成员 vs 非成员

重载方式 使用情况
成员函数 修改当前对象(如 +=),或左值必须是类对象(如 this + other
非成员函数 支持 a + b,其中 a 不是类类型(如 int + MyClass
友元函数 需要访问私有成员时使用非成员 + friend

最佳实践建议

  • 复合赋值运算符(+=, *= 等)使用成员函数实现;
  • 普通算术运算符(+, * 等)使用非成员函数,调用已有的复合赋值运算;
  • 适当使用 const& 引用避免复制。

三、最佳实践模板示例(二维向量)

#include <iostream>

class Vector2 {
public:
    float x, y;

    Vector2(float x = 0.0f, float y = 0.0f) : x(x), y(y) {}

    // 复合赋值:成员函数
    Vector2& operator+=(const Vector2& other) {
        x += other.x;
        y += other.y;
        return *this;
    }

    Vector2& operator-=(const Vector2& other) {
        x -= other.x;
        y -= other.y;
        return *this;
    }

    // 友元函数:普通加法
    friend Vector2 operator+(Vector2 lhs, const Vector2& rhs) {
        lhs += rhs;  // 复用 +=
        return lhs;
    }

    friend Vector2 operator-(Vector2 lhs, const Vector2& rhs) {
        lhs -= rhs;
        return lhs;
    }

    friend std::ostream& operator<<(std::ostream& os, const Vector2& v) {
        return os << "(" << v.x << ", " << v.y << ")";
    }
};

使用示例:

int main() {
    Vector2 a(1, 2), b(3, 4);
    Vector2 c = a + b;
    Vector2 d = a - b;

    std::cout << "a + b = " << c << "\n";
    std::cout << "a - b = " << d << "\n";
}

四、最佳实践原则总结

原则 说明
复用已有实现 实现 + 时复用 +=(拷贝 + 复合操作)
避免不必要复制 参数使用 const T&,返回值可按值返回(支持 RVO)
提供对称性 实现 a + b 时,也考虑实现 b + a(如 int + MyClass
使用 friend 仅限必要时 只有当需要访问私有成员,且不能用 getter 替代时
不滥用重载 不要让 * 表示“加权平均”,符号语义要符合预期
始终支持 ostream << 提升调试和输出体验(见上例)
保持操作不可变性 + 等操作符应当是不改变原对象的(除非是 +=

五、错误示例(反面教材)

Vector2 operator+(const Vector2& a, const Vector2& b) {
    a += b;  //  错误:不能修改 const 引用参数
    return a;
}

修正方法:

Vector2 operator+(Vector2 a, const Vector2& b) {
    a += b;
    return a;
}

六、如何支持标量乘法(左乘/右乘)

friend Vector2 operator*(const Vector2& v, float scalar) {
    return Vector2(v.x * scalar, v.y * scalar);
}

friend Vector2 operator*(float scalar, const Vector2& v) {
    return v * scalar;  // 复用上面的函数
}

七、C++20 三路比较

#include <compare>

class MyValue {
    int val;
public:
    auto operator<=>(const MyValue&) const = default;  // C++20 自动生成比较
};

八、最终推荐设计模板

操作符 类型 实现方式 是否成员
+= 复合赋值 成员函数
+ 通用加法 非成员 ✅(友元)
- 通用减法 非成员 ✅(友元)
* 标量或其他 非成员
<< 输出 非成员 ✅(友元)

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐