1.函数调用:
栈指针esp,帧指针ebp
函数调用过程:
push 参数2
push 参数1
call fun ;将下一条地址压栈
push ebp
mov ebp,esp
函数返回过程:
mov eax,[ebp-0x04] ;返回值 放在eax中
leave
ret
2.返回引用,与按值返回
不要返回局部变量的引用:
int& fun(){
int a=100;
return a;
}
void m_test(){
int a,b,c,d,e,f;
a=4;
b=1;
c=2;
d=5;
e=6;
f=7;
}
int main(){
int& c=fun(); //如果是int c=fun();这个地方已经将100拷贝到了c中,后面没有大问题,因为类型是int,如果是自定义类,会有大问题
cout<<"C before call m_test():"<<c<<endl;
m_test();
cout<<"C after call m_test():"<<c<<endl;
}
Result:
C before call m_test():100
C after call m_test():4
自定义类返回过程:
class ClassA{
public:
ClassA(int pa=1){
a=pa;
cout<<"Construct"<<endl;
};
ClassA(ClassA& p){
a=p.a;
cout<<"copy"<<endl;
}
ClassA& operator =(ClassA &p){
a=p.a;
cout<<"operator ="<<endl;
return *this;
}
~ClassA(){
a=0;
cout<<"Destroy"<<endl;
}
int a;
};
ClassA fun(){
ClassA x(2);
return x;
}
下面讨论三个main函数:
case1:
int main(){
ClassA& b=fun();
cout<<b.a<<endl;
return 0;
}
Result:
Construct ---1
copy ---2
Destroy ---3
2 ---4
Destroy ---5
分析:
---1:局部变量 x 的定义,调用构造。
---2:fun函数返回前,将 x 拷贝到 ”临时对象“。
---3:fun函数返回前,拷贝构造 ”临时对象“ 完成后,将局部变量(对象)x 销毁 即调用析构函数。返回后,ClassA的引用B同样指向 ”临时变量“
---4:输出b.a。
---5:销毁b。
注:由ClassA()调用而生成的临时对象却并不会在 表达式:ClassA& b=fun(); 结束之后立即被销毁,这个临时对象将会被引用到b上,在b的生命周期结束时,这个临时对象才被销毁。
case2:
int main(){
ClassA* b=&fun();
cout<<b->a<<endl;
return 0;
}
Result:
Construct ---1
copy ---2
Destroy ---3
Destroy ---4
0 ---5
分析:
---1:局部变量 x 的定义,调用构造。
---2:fun函数返回前,将 x 拷贝到 ”临时对象“。
---3:fun函数返回前,拷贝构造 ”临时对象“ 完成后,将局部变量(对象)x 销毁 即调用析构函数。
---4:返回后,将”临时变量“地址赋给ClassA的指针b。在表达式执行完成后,临时对象将被销毁,即调用析构函数。而b指向销毁的对象。
---5:因为b指向调用过析构函数的的对象,因此b->a的值为0。
注:如果不是保留临时对象的引用,而是保存了临时对象的地址,则不会有引用返回的特性,临时对象依然会在表达式结束后,马上自动销毁。
case 3:
int main(){
ClassA b=fun();
cout<<b.a<<endl;
return 0;
}
Result:
Construct ---1
copy ---2
Destroy ---3
2 ---4
Destroy ---5
分析:
---1:局部变量 x 的定义,调用构造。
---2:fun函数返回前,将 x 拷贝到 隐式“传”过来的参数:b对象中。
---3:fun函数返回前,拷贝构造完成后,将局部变量(对象)x 销毁 即调用析构函数。
---4:输出b.a(返回后不做与对象b相关的任何事)。
---5:销毁b。
注:case3与case1的区别在于,case3执行函数前,已经为对象b分配了存储空间,在fun返回时并没有生成“临时对象”,在这一点上,自定义类与基本类型变量有区别。
case 4:
int main(){
ClassA b;
b=fun();
cout<<b.a<<endl;
return 0;
}
Result:
Construct ---1
Construct ---2
copy ---3
Destroy ---4
operator = ---5
Destroy ---6
2 ---7
Destroy ---8
分析:
---1:main中,对象b的定义
---2:局部变量 x 的定义,调用构造。
---3:fun函数返回前,将 x 拷贝到 ”临时对象“。
---4:fun函数返回前,拷贝构造 ”临时对象“ 完成后,将局部变量(对象)x 销毁 即调用析构函数。
---5:完成b=临时变量 的赋值运算符重载 操作。
---6:临时变量销毁,调用析构。
---7:输出b.a。
---8:销毁b。