标签:
一.禁止函数返回局部变量的引用
当发生函数调用时,编译器首先把函数的输入/输出参数放到堆栈,指令寄存器IP放到堆栈(作为函数返回出口地址),然后是基址寄存器,接着是函数的局部变量。当函数返回时执行弹出操作,其顺序正好与放到堆栈的顺序相反(首先释放堆栈中的局部存储变量,然后是基址寄存器,IP寄存器地址和函数的输入/输出变量),同时把放到堆栈的IP寄存器地址作为函数的出口地址并退出函数。所以函数的所有局部变量都分配到了堆栈上,当函数退出时堆栈也就释放了,分配局部变量的内存被操作系统重新收回。而函数局部变量所在的内存段具体变成了什么,编程人员无法确定.
所以,函数返回时,保证返回数据超出函数范围后依然有效,如返回局部变量的引入就是不靠谱的事情
函数返回时,返回new生成的对象,同样不是一个可取的方法,因为这样的代码层次混乱,会让代码上层使用人员苦不堪言
二.函数传值。传指针及传引用的效率分析
值传递
char* GetMemory(int nNumber)
{
char* pStr = new char[nNumber];
return pStr;
}
int main()
{
char* pHello = NULL;
pHello = GetMemory(100);
strcpy_s(pHello,"Hello,World");
delete[] pHello;
pHello = NULL;
}
值传递调用过程分为三步:
1.在堆栈创建形参副本及局部变量
2.函数执行
3.函数退出,释放副本和临时变量。
在副本生成时,如果数据类型为类类型,函数会调用类的构造函数进行类对象构造和数据拷贝,在堆栈释放副本时,如果数据类型为类类型,函数会调用类的析构函数进行类对象数据的释放。
引用传递
char GetMemory(char* &pStr,int nNumber)
{
pStr = new char[nNumber];
return pStr;
}
int main()
{
char* pHello = NULL;
GetMemory(pHello,100);
strcpy_s(pHello,"Hello,World");
delete[] pHello;
pHello = NULL;
}
引用传值函数三步
1.在堆栈创建引用形参,普通形参副本及局部变量
2.函数执行
3.函数退出,释放(引用)副本和临时变量。
引用传值过程中,即使引用形参为类类型,在副本创建和释放时也不会发生构造和析构函数调用
指针调用3步
1.在堆栈创建指针形参,普通形参副本及局部变量
2.函数执行
3.函数退出,释放副本和临时变量
指针副本即使为类指针,也不会调用类的构造函数,因为创建的不是类对象,而是类指针
指针的解引用就是通常所说的间接寻址,即获取指针变量中内存地址处的数据
差异分析
1.值传递过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟内存空间以存放由主调函数传进来的实参值,从而成为实参的一个副本。被调函数对形式参数的任何操作都作为局部变量进行,不会影响主调函数的实参变量的值。如果想通过传值方式实现两数据的交换,则这种做法不正确。
2.引用传递过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成指针间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。下
标签:
原文地址:http://www.cnblogs.com/fenghuan/p/4855005.html