C和C++区别——前置自增与后置自增

一、先看下面两段完全一样的代码块

/* test.cpp */
int main()
{
    int a = 5;
    ++a = 7;
    printf("%d\n", a);
    return 0;
}
/* test.c */
int main()
{
    int a = 5;
    ++a = 7;
    printf("%d\n", a);
    return 0;
}

  在test.cpp文件与test.c文件下会分别显示什么呢?运行结果显示,在test.cpp下打印出 7 , 而在test.c下编译出错,报错信息:

二、前置自增

  乍一看++a = 7; 这条语句很奇怪,本以为会在C++里编译报错,没想到居然成功输出了7。

  学过C一定对前置自增“先+1,再返回”的操作很熟悉了,++a 会对a值先+1,再返回a当前的值(也就是6),注意在C里返回的是“值”(value)而不是 “引用”(reference),因此在test.c中 ++a = 7; 由于++a返回的是6这个右值,因此也就不能作为=的左操作数。

  而在C++里由于加入了引用这个概念,因此,++a会先对a值+1,再返回a的引用(是一个左值)。因此在C++标准中对于前置自增的运算符重载操作返回的也是 Object& 而不是 Object。

三、后置自增

  相对于前置自增,后置自增的操作是“先返回当前值,再+1”,也即 a++ 执行的是 int tmp = a; ++a; return tmp; 后置自增无论在C里还是C++里返回的都是值(Value),因此在后置自增上并没有太大的区别。由于后置自增返回的是值(Value),因此对于a++ = 7;这条语句,不论是在C++还是C中都会编译报错的。

  说到这可能有人会想到,既然C++里加入的引用可以作为前置自增的返回类型,为什么后置自增的返回不用引用呢?

  (1)首先,a++ <==> { int tmp = a; ++a; return tmp;  } ,tmp是一个临时变量,无法返回其引用。

  (2)在C++ Primer中明确说明了,C++中前置自增返回的是引用,后置自增则将对象原始值的副本作为右值返回既然要作为右值返回,后置自增的运算符重载的返回类型 就应该是 const Object,这样对于任何一个以 const Object作为返回类型的后置自增运算符重载,类似于 a++ = 7这样的语句都会报错,也即 a++返回了一个右值(rvalue)

四、运算符重载示例

  关于前置++后置++的重载,详细可查<<More Efficitive C++ >> 条款6;

class A {
public:
    A(int a) : m_data(a) {}

    A& operator++(){ //前置自增,返回 Object &
        m_data += 1;
        return *this;
    }

    const A operator++(int) {   //后置自增, 返回 const Object ,右值
        A tmp(m_data);
        ++*this;
        return tmp;
    }

    A& operator=(const A& a) {
        this->m_data = a.m_data;
        return *this;
    }
//private:
    int m_data;
};

/* test.cpp */
int main()
{
    A a(5);
    A b(10);
    ++a = b; // ++a返回a本身,>> a.m_data = 10;
    cout << a.m_data << endl;
    cout << (b++).m_data << endl; // b++返回tmp副本作为右值,>> 10
    //(b++) = a;  //error, b++返回的是右值

}

 

五、参考

  <<More Efficitive C++ >> 条款6;

  <<C++ Primer 5th 中文版>> 4.5 递增和递减运算符 

  

 

posted @ 2020-10-15 14:47  _程序兔  阅读(884)  评论(0编辑  收藏  举报