C++ 指针和引用、数组和指针、数组形参

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

====================================================||

欢迎讨论技术的可以相互加微信:windgs (请备注csdn+xx职业)

====================================================||

目录

 

1. 指针和引用

引用

指针

2. 指针和数组

auto与数组

decltype与数组

下标和指针

指向数组的指针

3. 数组形参

传递数组的引用

传递数组的指针


今天突然间看到一篇文章讲解指针和引用还有数组、指针、数值形参等,但是里面都是错误的,直接对指针进行指针+1,把指针的地址都给做偏移了,相信误导了很多的同学。所以随便写了下,希望对各位有点用处,不懂之处可以留言或者加wx

1. 指针和引用

引用

只是对象的别名。定义引用时,程序把引用和它的初始值绑定在一起,而不是将初始值拷贝给引用。定义一个引用之后,对该引用的所有操作都是在与之绑定的对象上进行的。

存在引用的引用、指针的引用

指针

就是内存的一块地址编号,存储这各种对象,所以存在对指针的引用。如,

存在指针的指针、引用的指针(形参的时候不可以)

int i = 42;
int *p = &i;
int *&r = p;


解析:离变量名最近的符号(此处是&)对变量有最直接的影响,因此 r 是一个引用。声明符的其余部分用以确定 r 引用的类型是什么,此例中的 int * 说明 r 引用的是int类型的指针。

例子:修改指针的值

2. 指针和数组

数组有一个特性:在很多用到数组名字的地方,编译器都会自动将其替换为一个指向数组首元素的指针!如,


auto与数组

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

int ia[] = {0,1,2};
auto ia2(ia);        // ia2 是一个int指针,指向ia的第一个元素!



decltype与数组

与之相反,当使用decltype关键字时,上述转换不会发生,decltype推断得到的类型就是原表达式真实的类型。

int A[] = { 0,1,2 };

decltype(A) B;        // B是一个数组,其大小为3
B[0] = 1;
B[1] = 2;
B[2] = 3;

for (auto i = begin(B); i != end(B); ++i) {
    cout << *i << " ";
}
cout << endl;

结果:1,2,3

下标和指针

对数组执行下标运算其实就是对指向数组元素的指针执行下标运算。如,

int *p = &A[2];
int i = p[-2];        // 其实就是 i=*(p-2)


内置的下标运算符所使用的索引值可以是负数。


指向数组的指针

首先,要讲一下多维数组:多维数组实际上是数组的数组,即数组的元素类型是数组。如,

int A[3][4];
A 是一个数组,大小为3,元素类型为 int[4],即元素类型为大小为4的 int数组。

多维数组名转换得来的指针实际上是指向第一个内层数组的指针:

int *ptrs[10];            // 指针数组

int (*p)[4] = A;        // 指向数组的指针
p = &A[2];


默认情况下,类型修饰符从右向左依次绑定。对 ptrs 来说,从右向左理解为:首先,[10] 说明我们定义的是一个大小为10的数组,它的名字为 ptrs,然后int*说明数组中存放的是指向int 的指针。
当声明带上了括号后,等于拥有了最先解释权:首先,圆括号括起来的部分(*p)说明p是一个指针,剩余部分则说明了指针所指向的对象的类型,此处是int[4],即大小为4的int数组;所以p是一个指针,指向一个大小为4的int数组。此处圆括号不可少!

3. 数组形参

注意,不存在元素类型为引用的数组!所以如下声明是错误的。

int &refs[10] = /* ? */;


引用一个数组:数组本身就是对象,所以允许定义数组的引用。如,

int B[4];
int (&ref)[4] = B;        // 引用一个大小为4的int数组


解释过程和指向数组的指针一样。首先看圆括号部分,(&ref)说明ref是一个引用,其余部分int[4]说明了ref引用的是一个大小为4的int数组。

 

使用数组时通常会将其转换为指针,所以当我们传递一个数组时,实际上传递的是指向数组首元素的指针。即使显式指定了数组大小,也没有用,因为编译器会忽略它!如下三个函数声明是等价的:

void print(const int*);
void print(const int[]);
void print(const int[10]);        // 都是一样编辑器已经做处理


以上函数的形参都是 const int* 类型的。数组的大小对该函数的调用没有影响。

通常情况下,可以显式传递一个表示数组大小的形参、或传递指向数组首元素和尾后元素的指针来解决以上问题。

void print(const int A[], size_t size);
void print(const int *beg, const int *end);


传递数组的引用

形参可以是数组的引用。此时,引用形参绑定到对应的实参上,也就是绑定到某个数组上。

// 维度是类型的一部分
void print(int (&arr)[10]);

传递数组的指针

数组不允许拷贝,所以我们无法以传值方式使用数组形参。

和所有数组一样,当将多维数组传递给函数时,真正传递的是数组首元素的指针。此时,传递的指针就是一个指向数组的指针,数组的第二维度的大小是数组类型的一部分,不能省略。

void print(int (*matrix)[10], int rowSize);


也可以使用数组的语法定义函数,此时编译器会一如既往地忽略掉第一个维度,所以最好不要把它包含在形参列表内:

void print(int matrix[][10], int rowSize);

猜你喜欢

转载自blog.csdn.net/Windgs_YF/article/details/88643179