[通俗易懂C++]:指针和const

发布于:2025-02-23 ⋅ 阅读:(13) ⋅ 点赞:(0)

之前的文章有说过,使用指针我们可以改变指针指向的内容(通过给指针赋一个新的地址)或者改变被保存地址的值(通过给解引用指针赋一个新值):

int main()
{
    int x { 5 };  // 创建一个整数变量 x,初始值为 5
    int* ptr { &x }; // 创建一个指针 ptr,指向 x 的地址(非 const 指针)

    int y { 6 };  // 创建一个整数变量 y,初始值为 6
    ptr = &y;  // 将 ptr 指向 y 的地址,我们可以改变它指向的地址

    *ptr = 7;  // 通过指针修改 ptr 所指向地址的值,即将 y 的值改为 7

    return 0;  // 程序成功结束
}

那么,如果我们想指向的值是const呢?

int main()
{
    const int x { 5 }; // x 现在是常量,值为 5
    int* ptr { &x };   // 编译错误:不能将 const int* 转换为 int*,因为 x 是常量,不能修改它的值

    return 0;  // 程序正常结束
}

这段代码会出现编译错误,因为我们尝试将一个指向 const int 类型的指针赋值给一个普通的 int* 指针,C++ 中不允许这样做。具体原因是 const 修饰符确保该变量的值在程序运行期间不能被修改,而普通的 int* 指针允许修改所指向的内容,所以会发生类型不匹配。


指向常量值的指针

指向常量值的指针(有时简称为指向 const 的指针)是一个(非 const)指针,它指向一个常量值。声明指向常量值的指针时,只需要在指针的数据类型之前使用const关键字。

int main()
{
    const int x {5};
    const int* ptr = {&x};
    
    *ptr = 6; // 非法操作:不能更改const值
   
    return 0;
}

在上面的示例中, ptr 指向一个 const int 。因为被指向的数据类型是 const,所以指向的值不能被更改。

然而,因此指向常量的指针本身不是常量(而是它的指向是一个常量),所以,我们可以通过给指针赋值=一个新的地址来改变指针指向的内容。

image-20250222224723856

int main()
{
    const int x {5};
    const int* ptr = {&x}; // ptr指向一个值为const的int类型的变量地址
    
    const int y {6};
    
    ptr = &y; // 指向一个新的地址
    
    std::cout << ptr << '\n';
    std::cout << *ptr << '\n';
    
    
    return 0;
}

就像 const 引用一样,指向 const 的指针也可以指向非 const 变量。指向 const 的指针将所指向的值视为常量,不管该地址上的对象最初是否被定义为 const

有点绕口,看个例子助消化:

int main()
{
    int x{ 5 }; // 非 const 变量,x 的初始值为 5
    const int* ptr { &x }; // ptr 是一个指向 const int 的指针,指向 x

    *ptr = 6;  // 不允许:因为 ptr 指向的是 "const int",所以不能通过 ptr 修改值
    x = 6; // 允许:因为 x 是非 const 的,直接修改 x 的值是可以的

    return 0; // 程序结束
}
  • **int x{ 5 };**这里定义了一个非 const 变量 x,并将其初始化为 5。
  • const int* ptr { &x };:定义了一个指向 const int 类型的指针ptr,它指向变量 x 的地址。虽然 x 是一个非 const 变量,但指针 ptr 被声明为指向 const 类型的对象。这样,ptr 不能修改所指向的值。
  • ***ptr = 6;**这是一个编译错误。虽然 x 是非 const 的,但由于 ptr 是指向 const int 的指针,编译器禁止通过该指针修改 x 的值。这是因为 ptr 被声明为指向常量,所以它会将 x 视为常量
  • **x = 6;**这行代码是允许的,因为 x 是非 const 的,直接通过变量名 x 修改其值没有问题。指针的 const 属性只影响通过指针访问数据时的行为,而不是通过普通的变量名。

常量指针

基于上述这些理论不难想到,我们也可以使指针本身成为常量。这就是常量指针,该指针是指其地址初始化后不能再次被更改。和普通的常量定义的概念是一致的,不过是将这个概念用在了指针类型上。

声明一个常量指针,在指针声明中的星号后面使用const关键字即可:

int main()
{
    int x{ 5 };
    int* const ptr { &x }; //星号之后的const意味着这是const指针

    return 0;
}
  • 在上述情况下, ptr 是一个指向(非 const)int 值的 const 指针。

  • 就像一个普通的 const 变量一样,const 指针必须在定义时初始化,并且这个值不能通过赋值来改变:

int main()
{
    int x{ 5 }; // 创建一个整数变量 x,初始值为 5
    int y{ 6 }; // 创建一个整数变量 y,初始值为 6

    int* const ptr { &x }; // const 指针 ptr 被初始化为指向 x 的地址
    ptr = &y; // 错误:一旦初始化,const 指针就不能改变它指向的地址

    return 0; // 程序正常结束
}

然而,因为所指向的值是非 const 的,可以通过解引用 const 指针来更改所指向的值:

 int main()
{
    int x{ 5 };
    int* const ptr { &x }; 

    *ptr = 6; 

    return 0;
}

最后,可以通过在类型和星号之前和之后都是用const关键字来声明一个指常量值的常量指针:

int main()
{
    int value { 5 };
    const int* const ptr { &value }; // 指常量值的常量指针

    return 0;
}

一个指向常量值的常量指针不能改变其地址,也不能通过该指针改变它所指向的值。它只能解引用以获取它所指向的值。


小结一下

  • 一个非 const 指针(例如 int* ptr )可以被分配另一个地址以改变它所指向的内容。
  • 一个常量指针(例如 int* const ptr )始终指向同一个地址,并且这个地址不能更改。
  • 一个指向非 const 值的指针(例如 int* ptr )可以改变它所指向的值。这些指针不能指向 const 值。
  • 一个指向常量值的指针(例如 const int* ptr )在通过该指针访问时将值视为常量,因此不能更改它所指向的值。这些指针可以指向常量或非常量左值(但不能指向右值,因为右值没有地址)。

感谢阅读、欢迎指正!