C++中指针、引用与const的深入解析

一、对数组的引用

const int n = 10;
int ar[n] = {12,23,34,45,56,67,78,89,100};
描述数组:类型加上原始空间大小。
​
int &ra = ar[1];
​
int &br = ar;//error
int (&br)[n] = ar;//ok
int *pa[10];
int &pr[10];//error;为什么不能编译成功
  1. 引用数组的概念:在 C++ 中,引用是一个别名,它必须被初始化以指向一个已经存在的对象。引用本身不是一个对象,它不能“存储”值,而是直接引用另一个对象的值。因此,引用类型不能用作数组的元素类型,因为数组的元素需要在数组创建时被默认初始化(如果它们没有显式初始化),而引用类型不能被默认初始化。

  2. 初始化问题:当声明一个数组时,数组的每个元素都需要被初始化(除非它们被显式地标记为未初始化,例如在某些类型的动态分配中)。然而,对于引用类型的数组,每个元素都需要一个已存在的对象来引用,这在数组声明时通常是不可能的,因为编译器不知道要引用哪些具体的对象。

  3. 编译器的限制:由于上述原因,C++ 标准不允许创建引用类型的数组。编译器在遇到这样的声明时会报错,因为它违反了引用的基本规则和数组的内存管理需求。

二、对指针的引用

int a = 10, b = 20;
int *p = &a;  //p是a指针,保存a的地址
int *s = p; //s是p的指针,保存p的地址
int *&rp = p;//rp是指针的引用,即是p的别名
​
*rp = 100;//通过解引用修改的是a的值
rp = &b;将p保存的地址修改为b的地址

三、例题,将指针,引用,const融合起来,分析

int main()
{
    int a = 10, b = 20;
    int* const p = &a;
    int* s1 = p;
    const int *s2 = p;
    int* const s3 = p;
    const int* const s4= p;
}

这是之前做过的一个例题,但是分析结果是所有都能编译通过,因为所有表达式都没有去试图修改p自身的值

如果改型为下述,分析结果

int main()
{
    int a = 10, b = 20;
    int* const p = &a;
    
    int* &s1 = p;
    const int *&s2 = p;
    int* const &s3 = p;
    const int* const &s4= p;
}

我们定义了一个常性指针,即p自身的值不能修改,所有试图能够修改p自身值的定义都不能被编译通过,接下来逐个分析:

①定义s1是p指针的引用,即s1是p的别名,如果修改s1自身,就会试图修改p的值,所以不能编译通过;

②定义s2是一个指向常量的指针的引用,仍然是p的别名,但是这个别名指向的位置是常性的,这意味着通过 s2,不能修改 p 指向的值,但可以让 s2指向另一个地址,即可以通过s2修改p的值,所以不能编译;

③定义s3作为一个常性指针的引用,即不可以通过s3改变p的值,但可以改变p指向的值,合法;

④s4是一个常性的指向常量的指针的引用,既不能修改 s4 指向的地址,也不能修改 s4指向的值。

四、总结

  1. 指针与引用的区别
    • 指针是一个变量,存储了另一个变量的内存地址。指针可以被重新赋值以指向其他对象,也可以进行算术运算。
    • 引用是一个别名,它必须被初始化以指向一个已经存在的对象,并且在初始化后不能改变其指向。引用更直观,更安全。
  2. 引用数组的概念与限制
    • 在C++中,不允许创建引用类型的数组,因为数组的每个元素需要在创建时被初始化,而引用类型不能被默认初始化。
    • 每个引用元素都需要引用一个已经存在的对象,这在数组声明时通常是不可能的。
  3. 指针的引用
    • 引用指针(即指针的引用)是合法的,并且可以用于改变指针所指向的地址。
    • 例如,int *&rp = p; 使得 rp 成为 p 的别名,通过 rp 可以修改 p 所指向的地址。
  4. const与指针、引用的结合
    • const int* p;p 是一个指向常量的指针,可以通过 p 读取所指向的值,但不能通过 p 修改所指向的值。
    • int* const p = &a;p 是一个常性指针,指向 int 类型变量 ap 本身的值(即它所存储的地址)不能被修改,但可以通过 p 修改所指向的 int 值。
    • 当 const 与指针的引用结合时,需要特别注意指针本身的常性(即指针的值是否能被修改)以及指针所指向对象的常性(即所指向的值是否能被修改)。
  5. 常见误区分析
    • 试图让非常性指针的引用指向常性指针是错误的,因为这会允许通过引用(一个非常性指针的引用)来“修改”(即重新赋值)常性指针所指向的地址。
    • 指向常量的指针的引用(即使该引用本身不是常性的)也不能用于改变常性指针所指向的地址,因为常性指针的值本身是不能被修改的。这里的错误在于混淆了指针的常性和所指向对象的常性。
    • 常性指针的引用是合法的,它允许通过引用(实际上是常性指针的别名)来访问或修改常性指针所指向的值,但不能改变常性指针所指向的地址。
    • 指向常量的常性指针的引用是最严格的,既不能改变所指向的地址,也不能修改所指向的值。

你可能感兴趣的:(c++,开发语言)