C++为什么不叫++C?——浅谈前自增与后自增的区别

C++ Primer 给我带来的惊喜与自增操作的奥秘
本文分享了一篇关于 C++ Primer 的文章,强调了这本书在内容严谨性和优秀习题方面的独特之处。重点解析了自增操作符的前置和后置形式,并通过具体例子解释了它们的区别。最后,文章深入探讨了 C++ 为何不被称为 ++C 的命名原因。

今天看到一个很有意思的文章,感觉挺有意思,所以转载过来,大家分享下:

原文地址:http://www.cnblogs.com/maxwellp/archive/2012/02/11/2346844.html

《C++ Primer》确实给我带来了很多惊喜。

作为一本专业的具有较高门槛的"入门书",它有很多地方实在是国内的书不可及的,这不仅在于内容上的严谨,更表现在优秀的习题所带给学习者的启迪。

 

习题5.16

你认为为什么C++不叫做++C?

 

看到这个习题,顿感眼前一亮(不禁想起某些国内书籍的题目,真是平淡如水),这对于理解前自增操作与后自增操作而言着实是个好的题目。

想弄明白这个问题,就需要先理解一些基础的概念。什么是自增操作呢?

 

++操作符,即自增操作符。自增操作符有两种形式:前置操作和后置操作。前自增操作生成左值,在给操作数加1后返回改变后的操作数值。后自增操作生成右值,给操作数加1但返回未改变的操作数原值。

*事实上,因为C++具有操作符重载的功能,自增操作不仅仅可以表示加1

 

前置操作返回的是加1后的值,返回的是对象本身,所以这是左值。

后置操作返回的是加1前的值,其返回值可以近似的理解为与原操作数值相等的常量,所以是一个右值。

 

具体例子:

 

int i = 0, j;
j = ++i; // j = 1 , i = 1:prefix yields incremented value
j = i++; // j = 1 , i = 2:postfix yields unincremented value

 

附左值与右值的概念:

 

左值:可以出现在赋值操作左边的值。非const左值可读可写。

右值:可用于赋值操作的右边但不能用于左边的值。右值只能读不能写。

 

左值可以出现在赋值操作右端,但右值不可以出现在赋值操作左端,将后自增操作置于赋值操作左端将会出现编译错误。

另外需要注意:

 

由于后置操作符要返回未加1前的值作为操作的结果,所以必须要保存操作数原来的值,对于比较复杂的类型,这种额外工作可能会花费更大的代价。

建议:只有在必要时才使用后置操作符。

 

最后,让我们用全新的角度去审视C++的命名原因

 

C++之名是Rick Mascitti在1983年夏天定名的(参见The C++ Programming Language(Special Edition)1.4节),C说明它本质上是从C语言演化而来的,“++”是C语言的自增操作符。C++语言是C语言的超集,是在C语言基础上进行的扩展(引入了new、delete等C语言中没有的操作符,增加了面向对象程序设计的直接支持,等等),是先有C语言,再进行++。根据自增操作符前、后置形式的差别,C++表示对C语言进行扩展之后,还可以使用C语言的内容;而写成++C则表示无法再使用C的原始值了,也就是说C++不能向下兼容C了,这与实际情况不符。 

 

如果以后有人问你这个问题,你会回答了吗?:)


置自(`++i`)和后置自(`i++`)的核心区别在于**表达式的返回值同**,尽管两者都会将变量的值加1。 --- ### 1. 置自(`++i`) - **先自,再使用**。 - 将变量 `i` 的值加1,然后返回**自后的结果**(即新值)。 - 返回的是一个**左值**(lvalue)。 #### 示例: ```cpp #include <cstdio> int main() { int i = 9; int result = ++i; // 先将 i 加1变成10,然后赋值给 result printf("result = %d, i = %d\n", result, i); // 输出: result = 10, i = 10 return 0; } ``` --- ### 2. 后置自(`i++`) - **先使用,再自**。 - 先返回 `i` 的当值作为表达式的结果,然后将 `i` 的值加1。 - 返回的是一个**右值**(rvalue),表示原始值的副本。 #### 示例: ```cpp #include <cstdio> int main() { int i = 9; int result = i++; // 先将 i 的原始值 9 赋给 result,然后 i 自为 10 printf("result = %d, i = %d\n", result, i); // 输出: result = 9, i = 10 return 0; } ``` --- ### 3. 在表达式中的行为差异 ```cpp #include <cstdio> int main() { int a = 5, b = 5; printf("++a = %d\n", ++a); // 输出 6,a 变为 6 printf("b++ = %d\n", b++); // 输出 5,b 变为 6 return 0; } ``` --- ### 4. 性能差异(尤其在C++类类型中) 对于内置类型(如 `int`),编译器通常会优化掉性能差异,`++i` 和 `i++` 性能几乎一样。 但对于**用户定义类型**(如迭代器、大对象),`i++` 需要创建一个临时对象来保存旧值用于返回,而 `++i` 需要。因此: - 在需要旧值的场景下(比如循环中),推荐使用 `++i`,效率更高。 - 特别是在 STL 迭代器中,应优先使用 `++iter` 而是 `iter++`。 #### 示例(STL风格): ```cpp for (auto it = vec.begin(); it != vec.end(); ++it) { // 推荐 // 处理 *it } ``` --- ### 总结对比表: | 特性 | `++i`(置) | `i++`(后置) | |------------------|--------------------------|------------------------------| | 执行顺序 | 先加1,后返回新值 | 先返回旧值,后加1 | | 返回值 | 自后的值(引用/左值) | 自的副本(右值) | | 是否产生临时对象 | 否(内置类型) | 是(用户类型,需保存旧值) | | 推荐使用场景 | 大多数情况,尤其循环 | 确实需要原值时才用 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值