用汇编的眼光看C++(之算术符重载)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】



算术符重载是类的有一个特性,但是每个人使用的方法不一样。用的好,则事半功倍;但是如果不正确的使用,则会后患无穷。 (1) 简单算术符介绍 那什么是算术符重载呢?我们可以举个例子。一般来说,我们定义两个int类型的变量的话,我们就可应对这两个类型进行加、减、乘、除的操作,同时还能比较判断、打印、数组操作、号操作等等。那么如果我们想自己定义的类也具有这样的属性,那我们应该怎么办呢?当然就要算术符重载了。首先,我们对基本class做一个定义:view plain
1. classdesk
2. {
3. public:
4. intprice;
5.
6. desk(intvalue):price(value) {}
7. ~desk() {}
8. desk& operator+= (desk& d){
9. this->price += d.price;
10. return
this;
11. }
12. };
下面,可以用一个范例函数说明一下使用的方法:view plain
1. 74: desk n(5);
2. 0040126D push 5
3. 0040126F lea ecx,[ebp-10h]
4. 00401272 call @ILT+0(desk::desk) (00401005)
5. 00401277 mov dword ptr [ebp-4],0
6. 75: desk m(10);
7. 0040127E push 0Ah
8. 00401280 lea ecx,[ebp-14h]
9. 00401283 call @ILT+0(desk::desk) (00401005)
10. 00401288 mov byte ptr [ebp-4],1
11. 76: n += m;
12. 0040128C lea eax,[ebp-14h]
13. 0040128F push eax
14. 00401290 lea ecx,[ebp-10h]
15. 00401293 call @ILT+40(desk::operator+=) (0040102d)
16. 77: }
大家可以把重点放在76句上面,不过74、75句我们也会稍微介绍一下: 74句: 创建desk类型的临时变量n,调用构造函数 75句: 创建desk类型的临时变量m,调用构造函数 76句: 两个desk类型的数据相加,但是在汇编的形式上面,我们发现编译器把这段代码解释成函数调用,也就是我们在上面定义的算术符重载函数。 (2)new、free重载 在C++里面,我们不光可以对普通的算术符进行重载处理,还能对new、free进行重载。通过重载new、free,我们还可以加深对代码的认识,正确认识构造、析构、堆内存分配的原理。 首先,我们对new和delete进行重载定义:view plain
1. classdesk
2. {
3. public:
4. intprice;
5.
6. desk(intvalue):price(value) {}
7. ~desk() {}
8. void operatornew(size_tsize) {returnmalloc(size);}
9. voidoperatordelete(void
pData) {if(NULL != pData) free(pData);}
10. };
那么使用呢?view plain
1. 72: desk d =newdesk(10);
2. 0040127D push 4
3. 0040127F call @ILT+65(desk::operatornew) (00401046)
4. 00401284 add esp,4
5. 00401287 mov dword ptr [ebp-18h],eax
6. 0040128A mov dword ptr [ebp-4],0
7. 00401291 cmp dword ptr [ebp-18h],0
8. 00401295 je process+56h (004012a6)
9. 00401297 push 0Ah
10. 00401299 mov ecx,dword ptr [ebp-18h]
11. 0040129C call @ILT+5(desk::desk) (0040100a)
12. 004012A1 mov dword ptr [ebp-24h],eax
13. 004012A4 jmp process+5Dh (004012ad)
14. 004012A6 mov dword ptr [ebp-24h],0
15. 004012AD mov eax,dword ptr [ebp-24h]
16. 004012B0 mov dword ptr [ebp-14h],eax
17. 004012B3 mov dword ptr [ebp-4],0FFFFFFFFh
18. 004012BA mov ecx,dword ptr [ebp-14h]
19. 004012BD mov dword ptr [ebp-10h],ecx
20. 73:deleted;
21. 004012C0 mov edx,dword ptr [ebp-10h]
22. 004012C3 mov dword ptr [ebp-20h],edx
23. 004012C6 mov eax,dword ptr [ebp-20h]
24. 004012C9 mov dword ptr [ebp-1Ch],eax
25. 004012CC cmp dword ptr [ebp-1Ch],0
26. 004012D0 je process+91h (004012e1)
27. 004012D2 push 1
28. 004012D4 mov ecx,dword ptr [ebp-1Ch]
29. 004012D7 call @ILT+0(desk::scalar deleting destructor') (00401005)</span>
30. <span style="margin: 0; padding: 0; border-style: none; color: rgba(0, 0, 0, 1); background-color: inherit">004012DC mov dword ptr [ebp-28h],eax</span>
31. <span style="margin: 0; padding: 0; border-style: none; color: rgba(0, 0, 0, 1); background-color: inherit">004012DF jmp process+98h (004012e8)</span>
32. <span style="margin: 0; padding: 0; border-style: none; color: rgba(0, 0, 0, 1); background-color: inherit">004012E1 mov dword ptr [ebp-28h],0</span>
33. <span style="margin: 0; padding: 0; border-style: none; color: rgba(0, 0, 0, 1); background-color: inherit">74: }</span>
上面是一段普通的new、delete使用代码。但是我们发现,简单的一个语句,在汇编器看来,却需要做这么多的内容,这是为什么呢,我们不妨来自习看一看: 72句:汇编中有两个函数调用,一个是new调用,也就是我们重定义的new函数,一个是构造函数,最后的几行代码主要是把构造函数返回指针赋值给一些临时变量,可忽略 73句:汇编中首先让指针和0进行了判断,然后调用了一个函数,似乎没有调用我们的delete函数,我们可以跟进去看一下:[view plain](http://blog.csdn.net/feixiaoxing/article/details/6785924#)
1. <span style="margin: 0; padding: 0; border-style: none; color: rgba(0, 0, 0, 1); background-color: inherit"><span style="margin: 0; padding: 0; border-style: none; color: rgba(0, 0, 0, 1); background-color: inherit">desk::
scalar deleting destructor':

2. 00401410 push ebp
3. 00401411 mov ebp,esp
4. 00401413 sub esp,44h
5. 00401416 push ebx
6. 00401417 push esi
7. 00401418 push edi
8. 00401419 push ecx
9. 0040141A lea edi,[ebp-44h]
10. 0040141D mov ecx,11h
11. 00401422 mov eax,0CCCCCCCCh
12. 00401427 rep stos dword ptr [edi]
13. 00401429 pop ecx
14. 0040142A mov dword ptr [ebp-4],ecx
15. 0040142D mov ecx,dword ptr [ebp-4]
16. 00401430 call @ILT+75(desk::~desk) (00401050)
17. 00401435 mov eax,dword ptr [ebp+8]
18. 00401438 and eax,1
19. 0040143B test eax,eax
20. 0040143D je desk::`scalar deleting destructor'+3Bh (0040144b)
21. 0040143F mov ecx,dword ptr [ebp-4]
22. 00401442 push ecx
23. 00401443 call @ILT+80(desk::operatordelete) (00401055)
24. 00401448 add esp,4
25. 0040144B mov eax,dword ptr [ebp-4]
26. 0040144E pop edi
27. 0040144F pop esi
28. 00401450 pop ebx
29. 00401451 add esp,44h
30. 00401454 cmp ebp,esp
31. 00401456 call __chkesp (00408810)
32. 0040145B mov esp,ebp
33. 0040145D pop ebp
34. 0040145E ret 4
上面的代码便是跟到0x401005之后遇到的代码,这里有一个跳转,真正函数开始的地方是0x401410。这里我们发现函数实际上还是调用了我们定义的delete函数和desk的析构函数。只不过析构函数一定要放在delete调用之前。所以,这里我们就看到了,c++中new的真正含义就是先分配内存,然后调用构造函数;而delete则是先对变量进行析构处理,然后free内存,这就是new和delete的全部意义。掌握了这个基础,可以帮助我们本地对内存进行很好的管理。
(3)friend算术符重载和普通算术符重载的区别 有一种算术符的重载是这样的:view plain
1. classdesk
2. {
3. intprice;
4. public:
5. desk(intvalue):price(value) {}
6. ~desk() {}
7. frienddesk operator+ (desk& d1, desk& d2);
8. };
9.
10. desk operator +(desk& d1, desk& d2)
11. {
12. desk d(0);
13. d.price = d1.price + d2.price;
14. returnd;
15. }
16.
17. voidprocess()
18. {
19. desk d1(3);
20. desk d2(4);
21. desk d = d1 + d2;
22. return;
23. }
感兴趣的同学可以汇编看一下,找一找它和普通的非友元函数有哪些区别。不过上面的代码还是让我们看出了一些端倪: a)友元函数不属于类,因为定义的时候我们发现没有desk::这样的前缀 b)友元算术符重载需要比普通的算术符重载多一个输入参数 c)友元函数在进行算术重载定义的时候需要多定义一个临时变量d,这在函数operator+()可以看出来 d)友元算术重载函数会破坏原来类地封装性 e)友元函数实际上就是全局函数

算术运算符使用的经验总结: (1)算术重载函数是一把双刃剑,务必小心使用 (2)内部算术符函数优先使用于非友元函数 (3)遇到 = 号重载特别注意一下指针 (4)重载的时候函数的内容要和重载的运算符一致,不用重载的是+,实际运算的是相减的内容 (5)除非特别需要重载,负责别重载 (6)重载的时候多复用已经存在的重载运算符 (7)new、delete除了内存管理和测试,一般不重载,全局new、delete严谨重载 (8)相关运算符重载要在stl中使用,务必注意返回值


原文链接: https://www.cnblogs.com/sier/archive/2011/09/21/5676485.html
欢迎关注*

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/32780

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月8日 上午9:55
下一篇 2023年2月8日 上午9:55

相关推荐