摘要:C++中存在两种参数传递方式,但语言存在上的数组与一般结构不同,它会在参数传递过程转化为指针,这是从C中继承下来。从而使得在函数中返回数组很困难。本文讲述几种可能的方法。
问题
我们在函数里面准备一个数组,或者说一组数据,现在想把这组数据返回到调用环境中去,就好比如下的代码:
something fun
(
)
{
int array [3 ] = { 1, 3, 4 } ;
return something ;
}
int main ( )
{
something = fun ( ) ;
return 0 ;
}
{
int array [3 ] = { 1, 3, 4 } ;
return something ;
}
int main ( )
{
something = fun ( ) ;
return 0 ;
}
可以说上面的代码看上去很优美,可是在C++如何实现那个fun函数呢?那个something具体是什么内容?
解答
非常遗憾,我没有办法在语言内置数组上实现如此优美的代码;如果我们使用用户数组如类似天vetor对象时,我可以写出这么优美的代码,但是在当前的C++标准(C++03)下它效率很低,在下一代标准中这一点可以实现。
让我们分析一下,要实现传递数组需要哪些准备:
- 首先数据存储的对象不能是自动生命期的,因为这样的话函数结束时,它会被销毁,所以它只能是静态生命期的或自由生命期的。
- 通过上面的分析我们产生出两种可能的解决方案:一是返回一个静态数组,二是返回一个动态数组,总之不能返回自动数组。
返回静态数组的方案大体代码如下:
int
* fun
(
)
{
static int array [3 ] = { 1, 3, 4 } ;
return array ;
}
{
static int array [3 ] = { 1, 3, 4 } ;
return array ;
}
这个方案有几个缺点:
- array的所有权是fun函数的,这个函数是全局的,所以array也是全局的,这意味着array是全局共享的,此时在多线程中必然不安全,甚至是灾难。不可行。
- 调用环境无法确定array的性质,甚至没有可行的办法知道array的大小,所以就算在单线程中也不具有十分安全。
- 用户无法更改array的性质,使得这样的函数使用的情况非常有限,不可能大面积使用。
之前的C中常有这种方案的出现,但C++不赞成这样使用,因为我们在C++似乎有一个比这个强一点的方案。
返回动态数组的方案要比返回静态数组的方案灵活多变,但也不是很完美,等到C++0x或者C++1x的时候可以改变这个情况。我们给出两个可能的示例代码:
int
* fun
(
size_t n
)
{
int * p = new int [n ] ;
//do something
return p ;
//这个方案最大缺点就是用户需要手工释放内存
//这在C++社区里不被支持,这些内存管理应该更自动化
}
//可能考虑使用智能指针
smart_ptr fun ( size_t n )
{
smart_ptr < int > p ( new int [n ] ) ;
//do something
return p ;
//这个方案似乎是最好的,它是效率与可用性的折中
//还有一个思路就是把整个数组都复制出去,它是最直观的,但是效率很差
//效率差在C++下一代标准中可以得到解决,所谓“右值引用”就是用来解决它的
//C++下一代标准叫做C++0x或C++1x,本站有相关内容
}
{
int * p = new int [n ] ;
//do something
return p ;
//这个方案最大缺点就是用户需要手工释放内存
//这在C++社区里不被支持,这些内存管理应该更自动化
}
//可能考虑使用智能指针
smart_ptr fun ( size_t n )
{
smart_ptr < int > p ( new int [n ] ) ;
//do something
return p ;
//这个方案似乎是最好的,它是效率与可用性的折中
//还有一个思路就是把整个数组都复制出去,它是最直观的,但是效率很差
//效率差在C++下一代标准中可以得到解决,所谓“右值引用”就是用来解决它的
//C++下一代标准叫做C++0x或C++1x,本站有相关内容
}
总之在现在有C++标准里没有一个高效的直观的方案来解决数组返回问题,人们往往采用其中比较折中的方案。