C++重载前后缀++,--

本文详细解释了C++中自增和自减操作符的前缀与后缀形式,包括参数规定、返回类型以及效率对比,帮助开发者更好地理解和应用这一特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先切记一句话前缀++比后缀++的效率高,返回引用的效率比返回对象的效率高,所以前缀++返回引用,后缀++返回对象。

在句法上,重载函数是通过它们的参数类型的差异区分的,但是不管是前缀形式还是后缀形式的自增和自减都没有参数,我们到底该怎么区分它们呢?在开始时,C++在语法上面确实是存在这个问题的,程序员对此颇有微词。后来C++中加了一些特性来解决这个问题。

C++规定后缀形式有一个int类型的参数,当函数被调用时,编译器传递一个0作为int参数的值给该函数。

且看下面的小程序:

#include <iostream>

 

class MyInt{

    public:

    MyInt(int a):i(a) {   }

 

    MyInt& operator++();            // prefix ++

    const MyInt operator++(int);    // postfix ++

 

    MyInt& operator--();            // prefix --

    const MyInt operator--(int);    // postfix --

 

    friend std::ostream& operator<<(std::ostream&,const MyInt&);

 

    private:

    int i;

};

 

MyInt& MyInt::operator++()

{

    this->i++;

    return *this;

}

 

const MyInt MyInt::operator++(int)

{

    const MyInt temp = *this;

    ++(*this);

    return temp;

}

 

std::ostream& operator<<(std::ostream& out,const MyInt& t)

{

    out << t.i ;

    return out;

}

 

int main()

{

     MyInt a(0);

    

     a++;

     std::cout << a << std::endl; // i = 1,print 1

     ++a;

     std::cout << a << std::endl; // i = 2,print 2

 

     std::cout << a++ << std::endl; // i = 3,print 2

 

     std:: cout << ++a << std::endl; // i = 4,print 4

     return 0;

}

 

看上面的程序可以发现以下几点:

1.       后缀形式的参数并没有被用到,它只是语法上的要求,为了区分而已;

2.       后缀形式返回一个const对象;这样做是大有深意滴~~ 我们知道操作符重载本质上是一个函数而已,它应该和操作符原来意义、使用习惯相似,而对于int内置类型来说的话,i++++是有语法错误的,故为了保持一致,重载之后的后缀形式也应该是这样的。假如返回的不是const类型,那么对于

MyInt t(1);

t++++;   // t.operator++(0).operator++(0)

这样的形式将是正确的,这显然不是我们期望的。另外,只要看上面的后缀形式的定义即可知道,这样写t只是增加了1而不是我们期望的2,为什么呢?因为第二次的调用是用第一次返回的对象来进行的,而不是用t,它违反了俺们程序员的直觉。因此,为了阻止这些行为,我们返回const对象。

3.       我们应该尽可能调用前缀形式;为什么呢?看看后缀形式的定义就可以知道,我们定义了一个临时对象,临时对象的创建、析构还是很费时间的。而前缀形式则不一样,它的效率应该相对好一些。

以上就是自增\自减操作符重载的前缀和后缀形式,我们只要记住那个参数规定和返回值形式,就很容易掌握啦。








### 置说明 在 C++ 中,`++` 是一种一元运算符,可以用于变量的自增操作。它可以分为 **前缀** 和 **后缀** 两种用法。通过运算符重载技术,开发者可以在类中定义 `++` 的行为。 以下是关于如何在 C++ 编程中重载 `++` 运算符的具体方法及其示例代码: --- ### 自增运算符重载的核心概念 #### 前缀 (`++obj`) - 表达的值是在执行加一之后的结果。 - 返回的是修改后的对象本身。 #### 后缀 (`obj++`) - 表达的值是在执行加一之的原始值。 - 需要返回一个临时的对象来表示未改变的状态。 为了区分这两种情况,在声明和定义时会使用额外的参数——通常是无意义的整型参数列表 `(int)` 来标记这是后缀版本[^1]。 --- ### 示例代码展示 下面是一个完整的例子,演示了如何在一个简单的类中实现 `++` 运算符的重载: ```cpp #include <iostream> using namespace std; class Counter { private: int value; public: // 构造函数初始化计数器 Counter(int v = 0) : value(v) {} // 前缀 ++ 实现 Counter& operator++() { ++value; // 对成员变量进行增量操作 return *this; // 返回对象引用 } // 后缀 ++ 实现 (注意多了一个 int 参数) Counter operator++(int) { Counter temp = *this; // 创建并保存旧状态副本 ++(*this); // 调用前缀版完成实际增加逻辑 return temp; // 返回保存的老数据作为结果 } void showValue() const { cout << "Current Value: " << value << endl; } }; // 测试程序部分 int main(){ Counter c1(5); cout << "Before Prefix Increment:" ; c1.showValue(); ++c1; // 使用前缀++ cout << "\nAfter Prefix Increment:\n"; c1.showValue(); cout << "\nBefore Postfix Increment:"; c1.showValue(); c1++; // 使用后缀++ cout << "\nAfter Postfix Increment:\n"; c1.showValue(); return 0; } ``` 上述代码展示了如何分别处理后缀的情况,并且每种情况下都提供了相应的解释[^2]。 --- ### 关键点解析 1. **前缀 vs 后缀** - 当用户调用 `++counter` 或者 `counter++` 时,编译器能够依据语法结构自动匹配到对应的重载函数[^3]。 2. **为什么后缀需要传入 int?** - 定义上区别开两者的关键在于签名差异;由于无法单纯靠名字区分同名不同语义的操作符,所以约定俗成地给后者附加了个假参表`(int)`以便于识别. 3. **效率考量** - 如果只关心性能而不考虑兼容性的话,则可能更倾向于仅提供前缀版本即可满足大部分需求场景下的应用。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值