起因:
上周碰到一同事与我基友探讨i++与++i效率问题。 一个坚持++i效率高于i++,一个确实不明白但坚持二者效率不重要。
其实这个效率本就可以忽虐不计。 正好当初学C++的时候算是深入研究过。当初还总结了一条自认为仞然正确的结论
进步的表现就是不断推翻甚至颠覆自己以往深思熟虑过的结论(不同境界就有不同的认知)
不过对于这个i++, ++i 只能装装用用吧。
1。执行先后顺序, n值大小问题
i = 0; n = i++ 与 n = ++i ; n 值大小的区别, 我觉得这个到没什么好说的, 丝毫没有新意。
2. c++ 中 前置 ++ 与 后置++的操作符的实现(当然是为了与内置类型保持一直的实现 )
++i 返回的是引用, i++返回的是旧值
//前置操作
Clazz& Clazz::operator++(){
//will evaluate something
return *this;
}
//后置操作
Clazz Clazz::operator++(int){
Clazz origin = new Clazz(*this);
++*this;
return origin;
}
3. 由第二个结论, 可以解释一种现象,++++clazz 能够执行 而 clazz++++确不能编译通过。
因为++clazz 返回的是引用, clazz++返回的是旧值.
当然对于内置类型就不一样了, 这两种方式在gcc 下都不能编译通过。
[root@jjy ~/q/exercise/c]# cat plusplusplusi.c
#include<stdio.h>
void main(){
int i = 0;
++++i;
printf("i++ == %d",i);
}
[root@jjy ~/q/exercise/c]# gcc plusplusplusi.c
plusplusplusi.c: 在函数‘main’中:
plusplusplusi.c:4:2: 错误:自增操作数必须是左值
++++i;
^
#include<stdio.h>
void main(){
int i = 0;
i++++;
printf("i++ == %d",i);
}
[root@jjy ~/q/exercise/c]# gcc iplusplus.c
iplusplus.c: 在函数‘main’中:
iplusplus.c:4:5: 错误:自增操作数必须是左值
i++++;
^
4. 由第二个结论还经常推论出第四个错误的结论,前缀++ 的效率优于后置++的效率
对于自定义类型, 前置++确实优于后置++,毕竟后置++调用了前置++,这倒没什么好说的。
但是对与内置类型, 比如int,其实效率是没有什么差距的
iplus.c与plusi.c文件
[root@jjy ~/q/exercise/c/test_iplusplius]# cat *.c
#include<stdio.h>
void main(){
int i = 0;
i++;
printf("i++ == %d",i);
}
#include<stdio.h>
void main(){
int i = 0;
++i;
printf("++i = %d",i);
}
效率测试过程,gcc -S 将源文件转化为汇编代码, 查看那二者汇编代码是否一直。
[root@jjy ~/q/exercise/c/test_iplusplius]# cat plusi.s
.file "plusi.c"
.section .rodata
.LC0:
.string "++i = %d"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movl $0, -4(%rbp)
addl $1, -4(%rbp)
movl -4(%rbp), %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 4.8.2"
.section .note.GNU-stack,"",@progbits
[root@jjy ~/q/exercise/c/test_iplusplius]# cat iplus.s
.file "iplus.c"
.section .rodata
.LC0:
.string "i++ == %d"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movl $0, -4(%rbp)
addl $1, -4(%rbp)
movl -4(%rbp), %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 4.8.2"
.section .note.GNU-stack,"",@progbits
<pre name="code" class="cpp">[root@jjy ~/q/exercise/c/test_iplusplius]# gcc -S iplus.c
[root@jjy ~/q/exercise/c/test_iplusplius]# gcc -S plusi.c
[root@jjy ~/q/exercise/c/test_iplusplius]# diff iplus.s plusi.s
1c1
< .file "iplus.c"
---
> .file "plusi.c"
4c4
< .string "i++ == %d"
---
> .string "++i = %d"
二者汇编码一直, 所以, 第四个结论应该是,
对于自定义类型, 前置++确实优于后置++,但是对与内置类型,二者没有什么差距(已在VC中验证)
其它相关:
对于 i = 0, i = i++ ; printf("%d", i) 这类问题本文不做讨论。