[C++]关于i++和++i的学习
MoaKap
今天在论坛上无意中看到有人问关于i++和++i的问题,感觉自己也不怎么熟悉,就仔细看了一下。感觉有位大侠的回复相当不错,很有特色,把问题讲得很明白,受教了。
这里摘录一下,学习学习!
--------------------------------------------------------------------------------------------------------
关于++i和i++的区别,如果用一个函数来说明,则它们分别等价于下面两个函数:
++i:
++i:
C/C++ code
int
ppi(
int
& i)
{
i = i +
1
;
return
i;
}
i++:
C/C++ code
int
ipp(
int
& i)
{
int
t = i;
i = i +
1
;
return
t;
}
显见,两个函数都将i的值加了1,但返回的值却不一样。另外,ipp比ppi多了
C/C++ code
int
t = i;
这步,所以++i的效率要比i++高一点。
--i和i--与此同理。
第二个问题: cout和printf多个输出时++i和i++的区别?
就是关于
cout<<i<<” “<<++i<<endl;与cout<<i<<” “<<i++<<endl;的区别
cout<<i<<” ”<<++i<<endl;与cout<<i<<” ”; cout<<++i<<endl;的区别
下面以一个例程来说明这个问题:
C/C++ code
#include <stdio.h>
#include <iostream.h>
int
main(
void
)
{
int
i =
0
;
cout <<
"Test execute order: "
<< endl
<<
"cout: "
<< i <<
", "
<< ++i << endl;
i =
0
;
printf(
"printf(): %d, %d/n"
, i, ++i);
return
0
;
}
这段代码在VC6.0、BC3.1下的执行结果是:
Test execute order:
cout: 1, 1
printf(): 1, 1
cout < < 实际上是执行了cout对象的重载操作符( < <)函数:
C/C++ code
ostream&
operator
<<( datatype );
这里的datatype是只相应的数据类型。该函数的调用之所以能写成cout < < "a" < < 3 < < "b" < < endl;这种拼接输出的形式,是因为它返回的是cout这个ostream对象本身,而返回的cout对象继续调用上面函数对下一个操作数进行输出,如此反复,直到该语句结束(当然,遇到刷新缓冲区的命令时还得先刷新)。由此可知,cout的执行顺序是从左到右的。
至于为什么i的值先被改变了呢?那是因为,C++标准对表达式的求解顺序不作规定,交给编译器决定。因此,各个编译器的实现也有点差异。例如,上面那个例程如果在gcc(g++)下执行的话,结果则是:
Test execute order:
cout: 0, 1
printf(): 1, 1
由此可知,VC、BC和gcc(g++)对这种拼接形式的表达式求解顺序不一样,后者是从左到右,前者是保持跟函数的顺序一样,即都是从右到左。而两者在对函数实参的表达式求解顺序却都是一样,即都是从右到左(看printf()的输出)。
因此。编程忠告不建议在同一个表达式里面同时修改同一个变量。
在平台:sparc-sun-solaris2.10-g++ (GCC) 4.0.3 (gccfss),结果是:
Test execute order:
cout: 0, 1
printf(): 1, 1
在平台:g++ (GCC) 3.4.6 20060404 (Red Hat 3.4.6-3),结果是:
Test execute order:
cout: 1, 1
printf(): 1, 1
这恰恰再次印证了“表达式求值顺序未定义”结论的正确性。
Test execute order:
cout: 0, 1
printf(): 1, 1
在平台:g++ (GCC) 3.4.6 20060404 (Red Hat 3.4.6-3),结果是:
Test execute order:
cout: 1, 1
printf(): 1, 1
这恰恰再次印证了“表达式求值顺序未定义”结论的正确性。
总结一下:
关于i++和++i:
1.二者都对i加1,但处理的顺序不同。i++先对i作相关运算,然后加1。++i先递增,然后再进行相关运算。
2.单独使用时,++i的效率要比i++效率高。
关于cout<<i<<i++<<endl;和cout<<i<<++i<<endl;有:
1. Cout是对<<运算符的重载,返回的是cout这个ostream对象本身。<<连续使用时,返回的cout对象继续调用上面函数对下一个操作数进行输出,如此反复,直到该语句结束。因此,cout执行顺序是从左到右。
2. C++标准对表达式的求解顺序不作规定,根据编译器不同而不同。因此,在不同的编译器环境下,cout<<i<<++i<<endl;输出并不总是按照cout从左到右的顺序执行。
3. 编译器函数实参的表达式处理顺序是从右向左。