zoukankan      html  css  js  c++  java
  • C和C++区别——前置自增与后置自增

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

    /* test.cpp */
    int main()
    {
        int a = 5;
        ++a = 7;
        printf("%d
    ", a);
        return 0;
    }
    /* test.c */
    int main()
    {
        int a = 5;
        ++a = 7;
        printf("%d
    ", 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 递增和递减运算符 

      

  • 相关阅读:
    《Linux内核设计与实现》读书笔记(十一) 定时器和时间管理
    《Linux内核设计与实现》读书笔记(十) 内核同步方法
    《Linux内核设计与实现》读书笔记(八) 中断下半部的处理
    《Linux内核设计与实现》读书笔记(七) 中断处理
    《Linux内核设计与实现》读书笔记(九) 内核同步介绍
    SQL Server数据库中使用sql脚本删除指定表的列
    如何删除在Excel中存在的无效的链接呢
    SQL Server游标使用快速上手
    SQL Server中查询某列所在的数据库中所在的表
    WinAPI: SetTimer、KillTimer 创建与移除高性能定时器
  • 原文地址:https://www.cnblogs.com/GuoYuying/p/13820500.html
Copyright © 2011-2022 走看看