转载:C++自增运算符的探索

来源:互联网 发布:梦里花落知多少全诗 编辑:程序博客网 时间:2024/06/01 09:35
转自:http://www.cnblogs.com/chenyuming507950417/archive/2012/04/19/2456966.html
复制代码
#include <iostream>using namespace std;int main(){    int a=5;    int b=++++a;    cout<<"b= "<<b<<"\t"<<"a= "<<a<<endl;    return 0;}
复制代码

运行结果:

b= 7    a= 7

复制代码
#include <iostream>using namespace std;int main(){    int a=5;    int b=(a++)++;    cout<<"b= "<<b<<"\t"<<"a= "<<a<<endl;    return 0;}
复制代码

运行结果:

发生编译错误:error C2105: '++' needs l-value

      我们知道:自增运算符++是结合方向是自右自左(VC++6.0),所以++++a也在写成++(++)a。根据++结合性,a++++肯定是错误的。至于(a++)++和++a++是否会发生错误,分析a++与++a后自会知道。

a++与++a的差别:

    (1)在运算过程中,先将对象进行递增修改,而后返回该对象(其实就是对象的引用)的叫前递增运算++a。在运算符重载函数中采用返回对象引用的方式编写。

    (2)在运算过程中,先返回原有对象的值,而后进行对象递增运算的叫后递增运算a++。在运算符重载函数中采用值返回的方式编写,重载函数的内部实现必须创建一个用于临时存储原有对象值的对象,函数返回的时候就是返回该临时对象。

    现在来分析下上面提出的问题:对于 (a++)++,先运算(a++),但(a++)返回的不是引用,而是原有a值的一个拷贝,而此时的拷贝不再是一个变量,还是一个常量,故不能当作左值继续参加括号外部的++运算。至于++a++,即++(a++),同样不能编译通过,原因是同样的道理。

自增运算符++的重载:

     在编写运算符重载函数的时候该如何区分前递增运算符重载函数与后递增运算符重载函数呢?方法就是:在后递增运算符重载函数的参数中多加一个int标识,标记为后递增运算符重载函数。

复制代码
#include <iostream>using namespace std;class Test{public:    Test(int a=0)    {        Test::a=a;    }    friend Test& operator++(Test&);    friend const Test operator++(Test&,int);public:    int a;};Test& operator++(Test& val)//前递增{    val.a++;    return val;}const Test operator++(Test& val,int)//后递增,int在这里只起到区分作用,没有实际意义{    Test temp(val);//这里会调用拷贝构造函数进行对象的复制工作    val.a++;    return temp;}int main(){    Test test(5);    ++++test;    cout<<"test.a= "<<test.a<<endl;    cout<<"后递增情况下临时存储对象的值状态:"<<(test++).a<<endl;    cout<<"test.a= "<<test.a<<endl;    Test test1(5);    (test1++)++;    cout<<"test1.a= "<<test1.a<<endl;    cout<<"前递增情况下临时存储对象的值状态:"<<(++test1).a<<endl;
    cout<<"test1.a= "<<test1.a<<endl;        return 0;}
复制代码

运行结果:

test.a= 7

后递增情况下临时存储对象的值状态:7

test.a= 8

test1.a= 6

前递增情况下临时存储对象的值状态:7

test1.a= 7

  上面代码是非成员格式,在《C++编程惯用法—高级程序员常用方法和技巧》中讲到对所有的一元操作符建议重载操作符函数为成员函数

复制代码
#include <iostream>using namespace std;class Test{public:    Test(int a=0)    {        Test::a=a;    }    Test& operator++();    const Test operator++(int);public:    int a;};Test& Test::operator++()//前递增{    this->a++;    return *this;}const Test Test::operator++(int)//后递增,int在这里只起到区分作用,没有实际意义{    Test temp(*this);//这里会调用拷贝构造函数进行对象的复制工作    this->a++;    return temp;}int main(){    Test test(5);    ++++test;    cout<<"test.a= "<<test.a<<endl;    cout<<"后递增情况下临时存储对象的值状态:"<<(test++).a<<endl;    cout<<"test.a= "<<test.a<<endl;    Test test1(5);    (test1++)++;    cout<<"test1.a= "<<test1.a<<endl;    cout<<"前递增情况下临时存储对象的值状态:"<<(++test1).a<<endl;    cout<<"test1.a= "<<test1.a<<endl;        return 0;}
复制代码

运行结果:

test.a= 7

后递增情况下临时存储对象的值状态:7

test.a= 8

test1.a= 6

前递增情况下临时存储对象的值状态:7

test1.a= 7

       在这里注意一点:为什么(test1++)++能编译通过,而上面提到的(a++)++却不能编译通过,这是因为进行(test1++)后,假设临时变量为temp,则temp=test1(原来的test1值),然后进行temp++,其实是进行的是temp.a++,而temp成员a是一个变量,所以可以进行自增运算。

  这里注意,红色标志的const是我后面加上去的,但加上去了,我上面的运行结果就会出错了,因为temp为const对象了,后面自然不能自增++了,而且我认为应该加const,避免(test1++)++这样出现。

  最后再想下,

  Test& operator++();

  const Test operator++(int);
  为什么一个返回引用,一个要返回const。

0 0
原创粉丝点击