一般来说,由于在离开函数后局部变量会被释放,所以是不允许函数返回指向局部变量的指针或引用的。我们往往需要遵循如下原则:
引用作为返回值,必须遵守以下规则:
(1)不能返回局部变量的引用。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。
(2)不能返回函数内部new分配的内存的引用。虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部new分配内存的引用),又面临其它尴尬局面。例如,被函数返回的引用只是作为一 个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放,造成memory leak。
(3)可以返回类成员的引用,但最好是const。主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果其它对象可以获得该属性的非常 量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。
但在有些时候,却允许返回局部变量的引用。其方法就是把局部变量声明为局部静态变量。如:
int& fun(void){
static int a;
return a;
}
我其实是在项目代码中看到这种用法的。其需求场景是这样的:某个成员函数需要在进行条件判断后,根据不同的条件返回不同的Mapping类对象的引用。大概如下:
const Mapping& Test::mapping() const //返回的是基类引用
{
if(condition1)
{
static MappingQ1 m; //这里是个派生类对象
return m;
}
else if(condition2)
{
static MappingQ2 m; //另一个派生类对象
return m;
}
}
可见,这个成员函数Test::mapping()是返回了局部对象的引用,其做法就是把局部对象声明为static,这样,就人为地把局部变量的生存周期改成了与整个源程序相同。所以这种方式返回局部变量的引用是安全的。
注:静态变量 表示在程序生存期会被保留下来到下次修改这个变量 有相当于全局变量的意义 ;
局部变量 表示在程序生存期会随着定义的作用域而消亡的变量 通常都是过度变量;