C/C++汇编角度浅析i++和++i的区别

赋值问题

编写代码
main.cpp:

1
2
3
4
5
6
7
8
9
10
int main(void)
{
    int = 0;
    int = ++a;
    int = 0;
    int = c++;
    return 0;
}

运行结果:

1
2
3
4
= 1
= 1
= 1
= 0

Alt + 8 反汇编调试发现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//int = 0;
0132139E  mov         dword ptr [a],0
//int = ++a;
013213A5  mov         eax,dword ptr [a] 
013213A8  add         eax,1 //这里有区别 
013213AB  mov         dword ptr [a],eax 
013213AE  mov         ecx,dword ptr [a] 
013213B1  mov         dword ptr [b],ecx 
//int = 0;
013213B4  mov         dword ptr [c],0
//int = c++;
013213BB  mov         eax,dword ptr [c]
013213BE  mov         dword ptr [d],eax //这里有区别  
013213C1  mov         ecx,dword ptr [c] 
013213C4  add         ecx,1
013213C7  mov         dword ptr [c],ecx

int b = ++a 是a先自增1之后再赋值给b,而 int d = c++ 则是先把c的值给d后c再自增,所以d的值为0,经过测试,函数返回时也会发生这个问题:

1
2
3
return i++;//此时函数返回i自增前的值
return ++i//此时返回i自增后的值

单行测试 i++ 和 ++i

1
2
3
4
int = 0;
i++;
int = 0;
++j;

反汇编代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
//int = 0;
0015139E  mov         dword ptr [i],0
//i++;
001513A5  mov         eax,dword ptr [i] 
001513A8  add         eax,1
001513AB  mov         dword ptr [i],eax 
//int = 0;
001513AE  mov         dword ptr [j],0
//++j;
001513B5  mov         eax,dword ptr [j] 
001513B8  add         eax,1
001513BB  mov         dword ptr [j],eax

发现汇编代码一样,说明单行使用++运算符时不影响赋值。

效率问题

在类相关的地方使用(例如:迭代器),会产生效率问题

重载++运算符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class CAge
{
public:
    CAge& operator++() //前置++
    {
        ++i;
        return *this;
    }
    const CAge operator++(int//后置++
    {
        CAge tmp = *this;
        ++(*this);  //利用前置++
        return tmp;
    }
    CAge& operator=(int i) //赋值操作  
    {
        this->i = i;
        return *this;
    }
private:
    int i;
};

STL vector迭代器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
std::vector<int> vct{ 123 };
auto itr = vct.begin();
//itr++
/*
_Myiter operator++(int)
{
    //这里需要定义临时变量
    _Myiter _Tmp = *this;
    ++*this;
    return (_Tmp);
}
*/
//++itr
/*
_Myiter& operator++()
{
++*(_Mybase *)this;
return (*this);
}
*/

迭代中,使用++运算符,只是为了让迭代器内置的指针+1而已,并不需要指针移动之前迭代器的副本,所以使用前置++会比后置++更加节省内存。换言之,复杂的循环中使用前置++会提高效率。

版权声明:xbinghai 发表于 2020-09-26 9:20:23。
转载请注明:C/C++汇编角度浅析i++和++i的区别 | 1号小说

暂无评论

暂无评论...