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 递增和递减运算符
C和C++区别——前置自增与后置自增的更多相关文章
- C++之前置自增与后置自增
关于前置自增与后置自增的区别我是参考这里:http://bbs.bccn.net/thread-454977-1-1.html 简单复述下,比如++x; 与 x++; 在C中,++x这个表达式的值为原 ...
- c++重在运算符前置自增和后置自增
class student { int age; }; int main() { class student stu; (stu++)++;//error ++(stu++);//error stu+ ...
- C: printf参数执行顺序与前置后置自增自减的影响
起源: 今天在了解副作用side-effect的过程中,看到了下面的网页,把我带到了由printf引起的一系列问题,纠结了一整天,勉强弄懂. 第一个代码没什么好解释的.而第二个printf(" ...
- HTML5 选择前置摄像头,选择后置摄像头
最近发现我写的都是乱七八糟的,觉得应该给大家带点福利,于是写了这篇 背景:最近想做个web应用,需要用到摄像头,但是发现默认一直是前置摄像头,拍照很麻烦,于是找了很多文章,居然没有人提到,只好FQ去找 ...
- c++ 前置++与后置++的区别
用C++编程的都知道,C++提供了一个非常强大的操作符重载机制,利用操作符重载,我们可以为我们自定义的类增加更多非常有用的功能.不过,C++也有限制,就是当我们为自定义的类重载操作符时,重载操作符的含 ...
- C++之运算符重载(前置++和后置++)
今天在阅读<google c++ 编程风格>的文档的时候,5.10. 前置自增和自减:有一句话引起了我的注意: 对于迭代器和其他模板对象使用前缀形式 (++i) 的自增, 自减运算符.,理 ...
- C++中前置操作符和后置操作符的重载
1,C 语言中讨论了原生含义,C++ 中有必要考虑前置.后置操作符能够重载,有何问题: 2,值得思考的问题: 1,下面的代码有没有区别?为什么? 1,i++ // i 的值作为返回值,i 自增 1: ...
- android Camera 如何判断当前使用的摄像头是前置还是后置
现在 android 平台的智能手机一般都标配有两颗摄像头.在 Camera 中都存在摄像头切换的功能. 并且有一些功能前后置摄像头上会有所不同.譬如人脸检测,人脸识别,自动对焦,闪光灯等功能, 如果 ...
- pytest_前置后置
今天总结下pytest,pytest简直就是python自动化中的高富帅,各种操作,哈哈 这次总结主要涉及到了以下几点: 1.unittest中的setUp.tearDown.setUpClass.t ...
随机推荐
- TonWeb6.1Linux安装文档
东方通部署文档 东方通安装部署文档 准备文件:开始安装:警告:在安装之前先安装JDK,JDK要求JDK5以上Linux安装:运行安装包sh Install_TW6.1.5.15_Standard_ ...
- Java查找指定文件中指定字符的个数
package lwl.youweb2.test; import java.io.BufferedReader; import java.io.FileReader; import java.io.I ...
- vue父子传值与非父子传值
大概梳理下传值的几种方式 一:父子组件传值 props方式 子组件对外暴露方法并向父组件传递由于触发方法导致的值的变化,父组件接收子组件传递来的值:子组件接收父组件传递来的值,并根据传递来的值在子组件 ...
- matplotlib | Python强大的作图工具,让你从此驾驭图表(二)
今天是数据处理专题的第10篇文章,我们继续来聊聊matplot这个工具库. 在上周的文章当中我们介绍了matplot的基本用法,以及展示了一些简单的例子,让大家直观地了解这个工具包.我们可以简单地将它 ...
- Python实现GUI开发 PySide2&PyQt环境配置
更新于2020-09-15 - 18:50:37 [前言] 关于Python开发GUI图形界面程序的问题,大概是19年十分困扰我,主要是没有经验以及缺乏高效简洁的视频或教学文档,导致在19年中秋前后花 ...
- k8s volume存储卷
k8s volume存储卷 介绍 volume存储卷是Pod中能够被多个容器访问的共享目录,kubernetes的volume概念,用途和目的与docker的volume比较类似,但两者不能等价, ...
- tomcat源码之概述
tomcat架构及常用的组件如下: Server Server代表了tomcat服务器,Tomcat启动时即会启动一个server实例,它监听在8005端口以接收shutdown命令,使用 telne ...
- Docker:常见命令
Docker常见命令(持续更新中): 说明 命令 截图 1 查看Docker版本 Docker -v 2 查看镜像 Docker image ls 3 查看容器 Docker conta ...
- HTML+CSS使用swiper快速生成最简单、最快捷、最易看懂的轮播图
1. 在网页顶部输入swiper.com.con,进入swiper官网 2. 点击" API文档",获取轮播图代码的地方 3. 点击左侧"swiper初始化&q ...
- 实现图片的上传(要求:上传到指定的FTP服务器)
考核的知识点: (1)Linux系统的使用 (2)tengine 纯HTTP的web服务器 (3)SpringMVC的上传功能 (4)FTP的数据传到 1.1 传统上传方式的问题 但是在 ...