C/C++ 返回及动态创建指向数组指针


  在上一篇文章 “C/C++ 指针,数组与退化” 中我们详细解释了如何声明指向数组的指针,在实际应用中,仅仅静态声明一个数组或者其指针是不够用的,还需要返回及动态创建。

返回指向数组指针的函数

基本方法

  声明一个返回数组指针的函数的基本形式如下: Type (*function (parameter_list)) [dimension]

  不过我们理所当然的可以对其进行扩展: Type (*function (parameter_list)) [dimension1][dimension2]...

  所以,一个基本的返回一维数组的指针的函数如下:


int(*func())[6]//C++ Primer解释为,可以对函数结果进行解引用,因为这个函数的返回值是左值
{
	int b[6] = { 1,2,3,4,5,6 };
	int(*n)[6] = &b;
	return n;
}

  ** 注意:任何声明都严格匹配维度 **

  返回二维数组的指针的函数如下:


int(*func2())[3][2]
{
	int b[3][2] = { 1,2,3,4,5,6 };
	int(*n)[3][2] = &b;
	return n;
}

使用类型别名

  由于这种写法并不是很清晰,所以 C/C++ 也允许使用类型别名的方式声明:


typedef int arrT[10];//C,arrT表示一个含有10个元素的整形数组
using arrT = int[10];//C++
arrT* func();

  推广开来:


typedef int arrT[3][2];//C,arrT表示一个3x2的二维数组
using arrT = int[3][2];//C++
arrT *func()
{//注意此时*与func()优先结合,而不是与类型别名结合
	int b[3][2] = { 1,2,3,4,5,6 };
	int(*n)[3][2] = &b;
	return n;
}

尾置返回类型

  不过使用类型别名其实不是很优雅,首先多了一条语句,其次你需要知道 * 的结合顺序,所以 C++ 11 增加了一种新的方法尾置返回类型:


auto func() -> int(*)[10];
auto func2() -> int(*)[3][2];

  根据前文我们知道,声明一个指向数组的指针是这样的:


int a2[3][2] = {1,2,3,4,5,6};
int (*b2)[3][2] = &a2;

  尾置返回类型的结构中就直接使用了和声明指针一样的方法,只不过去掉了用户标识符。

decltype 关键字

  如果我们在同一个作用域有一个现成的数组,并且确定这个数组是这个函数相关的,那么我们还可以使用 decltype 关键字匹配类型简化声明:


int odd[] = {1,3,5,7,9};
int even[] = {0,2,4,6,8};
decltype(odd) *arrPtr(int i)
{
	return (i % 2) ? &odd : &even;
}

使用 new 动态创建并返回指针

  使用 new 操作符获得一个指向二维数组的指针更是轻车熟路:


int(*n1)[3] = (int(*)[3])new int[3];
int(*n2)[3][2] = (int(*)[3][2])new int[3][2];

参考:C++ Primer 第五版 206 页