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

2014-11-24 12:43:50 · 作者: · 浏览: 2
eax,eax

0040143D je desk::`scalar deleting destructor'+3Bh (0040144b)

0040143F mov ecx,dword ptr [ebp-4]

00401442 push ecx

00401443 call @ILT+80(desk::operator delete) (00401055)

00401448 add esp,4

0040144B mov eax,dword ptr [ebp-4]

0040144E pop edi

0040144F pop esi

00401450 pop ebx

00401451 add esp,44h

00401454 cmp ebp,esp

00401456 call __chkesp (00408810)

0040145B mov esp,ebp

0040145D pop ebp

0040145E ret 4

desk::`scalar deleting destructor':

00401410 push ebp

00401411 mov ebp,esp

00401413 sub esp,44h

00401416 push ebx

00401417 push esi

00401418 push edi

00401419 push ecx

0040141A lea edi,[ebp-44h]

0040141D mov ecx,11h

00401422 mov eax,0CCCCCCCCh

00401427 rep stos dword ptr [edi]

00401429 pop ecx

0040142A mov dword ptr [ebp-4],ecx

0040142D mov ecx,dword ptr [ebp-4]

00401430 call @ILT+75(desk::~desk) (00401050)

00401435 mov eax,dword ptr [ebp+8]

00401438 and eax,1

0040143B test eax,eax

0040143D je desk::`scalar deleting destructor'+3Bh (0040144b)

0040143F mov ecx,dword ptr [ebp-4]

00401442 push ecx

00401443 call @ILT+80(desk::operator delete) (00401055)

00401448 add esp,4

0040144B mov eax,dword ptr [ebp-4]

0040144E pop edi

0040144F pop esi

00401450 pop ebx

00401451 add esp,44h

00401454 cmp ebp,esp

00401456 call __chkesp (00408810)

0040145B mov esp,ebp

0040145D pop ebp

0040145E ret 4

上面的代码便是跟到0x401005之后遇到的代码,这里有一个跳转,真正函数开始的地方是0x401410。这里我们发现函数实际上还是调用了我们定义的delete函数和desk的析构函数。只不过析构函数一定要放在delete调用之前。所以,这里我们就看到了,c++中new的真正含义就是先分配内存,然后调用构造函数;而delete则是先对变量进行析构处理,然后free内存,这就是new和delete的全部意义。掌握了这个基础,可以帮助我们本地对内存进行很好的管理。

(3)friend算术符重载和普通算术符重载的区别

有一种算术符的重载是这样的:

class desk

{

int price;

public:

desk(int value):price(value) {}

~desk() {}

friend desk operator+ (desk& d1, desk& d2);

};

desk operator +(desk& d1, desk& d2)

{

desk d(0);

d.price = d1.price + d2.price;

return d;

}

void process()

{

desk d1(3);

desk d2(4);

desk d = d1 + d2;

return;

}

class desk

{

int price;

public:

desk(int value):price(value) {}

~desk() {}

friend desk operator+ (desk& d1, desk& d2);

};

desk operator +(desk& d1, desk& d2)

{

desk d(0);

d.price = d1.price + d2.price;

return d;

}

void process()

{

desk d1(3);

desk d2(4);

desk d = d1 + d2;

return;

}

感兴趣的同学可以汇编看一下,找一找它和普通的非友元函数有哪些区别。不过上面的代码还是让我们看出了一些端倪:

a)友元函数不属于类,因为定义的时候我们发现没有desk::这样的前缀

b)友元算术符重载需要比普通的算术符重载多一个输入参数

c)友元函数在进行算术重载定义的时候需要多定义一个临时变量d,这在函数operator+()可以看出来

d)友元算术重载函数会破坏原来类地封装性

e)友元函数实际上就是全局函数

算术运算符使用的经验总结:

(1)算术重载函数是一把双刃剑,务必小心使用

(2)内部算术符函数优先使用于非友元函数

(3)遇到= 号重载特别注意一下指针

(4)重载的时候函数的内容要和重载的运算符一致,不用重载的是+,实际运算的是相减的内容

(5)除非特别需要重载,负责别重载

(6)重载