C++ 数组 指针 引用 函数声明引起的混乱辨析......

int array[] = { 1,2,3,4 }; //数组本质是个int指针,指向第一个元素
int* int_ptr = array;      //int指针指向数组的第一个元素
int& int_ref = *int_ptr;   //第一个元素的引用

printf("%p %p %p\n", array, int_ptr, &int_ref);
printf("%p %p %p\n", array+1, int_ptr+1, &int_ref+1);

// 输出
00EFF8D0 00EFF8D0 00EFF8D0
00EFF8D4 00EFF8D4 00EFF8D4

数组本身是一个元素指针,除了元素类型信息以外不携带任何关于这个数组的信息。

但是有意义的是对数组取地址得到却不是一个int**这么简单:

// int(*array_ptr)[3] = &array; // 编译器会报错,int(*)[4]类型的值不能用于初始化int(*)[3]
类型的实体
// int** int_p_p = &array;      // 编译器会报错,int(*)[4]类型的值不能用于初始化int**类型的实体

看来编译器会检查右值的类型,这说明数组的指针携带了所指向的数组的类型和长度信息,并不是简单将数组当作int指针又取了一次地址而已 。

借两张图来帮助记忆。来自https://www.cnblogs.com/zero-waring/p/12776044.html的两张图

定义数组的指针和引用的写法比较复杂,如果不用等价声明typedef或者using的方式的话。

int(*array_ptr_1)[4] = &array; // 定义一个长为4的int型数组的指针,并将array的地址赋给这个指针
    // 这个看起来有点复杂的声明的解读:
    // (*array_ptr_1) 说明array_ptr_1是一个可以解引用的变量
    // (*array_ptr_1)[4]说明解引用之后是一个四个元素的数组, int xxxxxx说明这个数组的元素类型是int
    //                     ---(c++primer)
int(&array_ref_1)[4] = array;  // 几乎同等烧脑的数组引用的声明方式。

// 改用数组等价声明方式
using a_int_4 = int[4];        
a_int_4* array_ptr_2 = &array; // 这种声明方式可以产生和array_ptr_1一摸一样的数据类型
a_int_4& array_ref_2 = array;

int array_ptr_3[2][4];   //多维数组的声明,按理说array_ptr_3应该是一个指向int[4]的指针

// 下面将其地址和偏移特性都打出来看一下
printf("%p %p %p %p %p\n", array_ptr_1, array_ptr_2, &array_ref_1, &array_ref_2,array_ptr_3);
printf("%p %p %p %p %p\n", array_ptr_1 + 1, array_ptr_2 + 1, &array_ref_1+1, &array_ref_2+1, array_ptr_3 + 1);

00B3F768 00B3F768 00B3F768 00B3F768 00B3F6F8
00B3F778 00B3F778 00B3F778 00B3F778 00B3F708

五者的偏移都是16bytes,说明指针携带了对象的元素和长度信息。

跟函数的形参、返回值声明搅和在一起之后就更加烧脑了。

void func(int( *array_ptr)[4], int(& array_ref)[4]); // 做形参的时候还好,跟上面一样的

做返回值的时候就... 

int(*func_returns_array_ptr())[4]{
	int (*xx)[4] = new int[3][4];
	printf("%p <--malloc in func_returns_array_ptr\n", xx);
	return xx;
}//😂

int(&func_returns_array_ref())[4]{
	int(*xx)[4] = new int[3][4];
	printf("%p <--malloc in func_returns_array_ref\n", xx);
	return *xx;
}//🤣🤣🤣


// 调用也古怪
int(*array_ptr_ret)[4] = func_returns_array_ptr();
int(&array_ref_ret)[4] = func_returns_array_ref();
printf("%p %p\n", array_ptr_ret, &array_ref_ret);
printf("%p %p\n", array_ptr_ret + 1, &array_ref_ret + 1);

printf("%p <-array_ptr_ret\n",array_ptr_ret);
delete array_ptr_ret;
printf("%p <-&array_ref_ret\n", &array_ref_ret);
delete &array_ref_ret;



好在结果看起来是对的
01496BB0 <--malloc in func_returns_array_ptr
014968D8 <--malloc in func_returns_array_ref
01496BB0 014968D8
01496BC0 014968E8
01496BB0 <-array_ptr_ret
014968D8 <-&array_ref_ret

还是老老实实用typedef或者using吧亲。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值