小心:数组作为形参以及返回数组指针

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wk_bjut_edu_cn/article/details/82024739

数组作为形参知识点

1.数组的维度必须是一个常量表达式

int main(void)
{
	constexpr int i = 20;
	int j = 5;//不是常量表达式
	int arr1[i];//正确
	int arr2[j];//错误
	system("pause");
	return 0;
}

2.默认情况下,数组的元素被默认初始化。而且需要注意的是,和内置类型的变量一样,如果在函数内部定义了某种内置类型的数组,那么默认初始化会令数组有未定义的值。

什么是默认初始化?

如果定义变量时没有指定初值,则变量被默认初始化,此时变量被赋予默认值。默认值到底是什么有两个决定因素,一是变量类型;二是定义变量的位置。如果是内置类型的变量未被初始化,它的值由定义的位置决定。定义于任何函数体之外的变量被初始化为0.定义于函数体内部的内置类型变量将不被初始化。一个未被初始化的内置类型变量的值是未定义的。如果试图拷贝或以其他方式访问此类值将引发错误。

#include<iostream>
using namespace std;
int main(void)
{
	int arr[5];
	cout << arr[2] << endl;
	system("pause");
	return 0;
}

#include<iostream>
using namespace std;
int arr[5];
int main(void)
{
	cout << arr[2] << endl;
	system("pause");
	return 0;
}

3.定义数组的时候必须指定数组的类型,不允许用auto关键字由初始值的列表推断类型。

auto int arr[5] = { 1,2,3,4,5 };//错误

4. 数组的两个特殊性质

(1)不允许拷贝数组
(2)使用数组时(通常)会将其转换为指针

比如当使用数组作为一个auto变量的初始值时,推断得到的类型是指针而非数组

int i = 6;
	int *p = &i;
	int arr[] = { 1,2,3 };
	auto a(arr);
	a = p;//正确

但是当使用关键字decltype关键字时上述转换不会发生 

	int i = 6;
	int *p = &i;
	int arr[] = { 1,2,3 };
	decltype(arr) a;
	a = p;//错误,不能把整型指针给数组赋值
	a[1] = 6;//正确

5.由于4的两个性质,所以我们无法以值传递的方式使用数组参数。因为数组会被转换为指针,所以当我们为函数传递一个数组时,实际上传递的是指向数组首元素的地址

//尽管形式不同,但下面3个fcn函数是等价的,每个函数
//都有一个const int*类型的形参,所以不属于重载
void fcn(const int*){}
void fcn(const int[]) {}
void fcn(const int[10]){}

6.C++允许将形参定义成数组的引用,此时引用形参绑定到对应的实参上,但是,不同于5,此时的数组不是以指针形式存在

也就是说:

//属于重载,因为维度的不同
void fcn(int (&arr)[10]){}
void fcn(int (&arr)[20]){}
#include<iostream>
using namespace std;
void print(int(&arr)[5])
{
	for (auto elem : arr)
		cout << elem << endl;
}
int main(void)
{
	int a1[3] = { 1,2,3 };
	int a2[5] = { 1,2,3,4,5 };
	//print(a1);错误:实参不是含有5个整数的数组
	print(a2);
	system("pause");
	return 0;
}

返回数组指针知识点

因为数组不能被拷贝,所以函数不能返回数组。不过,函数可以返回数组的指针或引用。

1.使用类型别名

//下面两者的arr都是类型别名,它表示的类型是含有10个整数的数组
typedef int arr[10];
using arr = int[10];
//fun返回一个指向含有10个整数的数组的指针
arr* func(int i);

2.直接返回

int(*func(int i))[10];

fun(int i)表示调用func函数需要int类型的实参。

(*func(int i))表示函数返回一个指针

int (*func(int i))[10]表示返回的指针是指向一个int类型的数组

插叙:如何阅读C++中的复杂声明

黄金法则:从标识符开始(或者最内层的结构,如果不存在标识符的话,通常出现于函数指针),首先向右看,直到遇到 ) 括号或者结束,看到什么就说出来;然后向左看,直到遇到 ( 括号或者回到行首,看到什么就说出来。跳出一层括号,重复上述过程:右看看,说出来;左看看,说出来。直到你说出变量的类型或者返回值(针对函数指针),也就表示你把声明都读完了。

int (*(*vtable)[])();

这是一个指针,指向一个数组,数组的每个元素是一个指向返回值是int类型函数的指针

3.使用尾置返回类型

C++11新标准中的方法,任何函数的定义都能使用尾置返回类型,但是这种形式对于返回类型比较复杂的函数声明最有效。

//fun接受一个int类型的实参,返回一个指针,该指针指向含有10个整数的数组
auto func(int i) -> int(*)[10];

4.使用decltype

int arr[] = { 1,2,3,4,5 };
decltype(arr) *func(int i);

注意:前面说过,decltype所说明的arr是一个数组,要想func返回指针必须在函数声明时加一个*

猜你喜欢

转载自blog.csdn.net/wk_bjut_edu_cn/article/details/82024739
今日推荐