banner
cells

cells

为美好的世界献上 code

關於指標常量與常量指標

指標常量#

int *const ptr = nullptr;

const 修飾的是指標 ptr 的值,ptr 本身不能被修改,所以指標常量必須初始化,同時我們無法對 ptr 的值進行修改。

int a = 10;
int *const ptr = &a;
ptr = nullptr; // 錯誤

指標常量的應用場景#

例如:需要編寫一個函數,實現使用傳參指標的形式交換兩個整數的值。

下面是實現代碼:

void swap(int *a, int *b) {
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

上述代碼可以實現功能,但是存在一定的問題,因為我們可以在函數體內可以修改指標的所指向的值,同時也可以修改指標的值(這並不是我們所希望的),為了使代碼更為健壯,我們可以使用指標常量,使得傳入指標的值不會被無意修改。

下面是修改後的代碼:

void swap(int *const a, int *const b) { ... }

常量指標#

const int *ptr;
// 或
int const *ptr;

const 修飾的 *ptr 的值,也就是指標所指向的值,ptr 指向的值是不可修改的。同時在不進行常量類型轉換的情況下我們無法對 *ptr 進行修改。

int a = 10;
int const *ptr = &a;
*ptr = 20; // 錯誤

常量指標的應用場景#

例如:需要編寫一個函數,實現打印一個數組。

下面是實現代碼:

void printArray(int const* arr, size_t len) {
    for (size_t i = 0; i < len; ++i) {
        std::cout << arr[i] << " ";
    }
}

這裡你可能會認為使用 const 修飾數組退化而來的指標所指向的值就可以了,但是這仍存在的問題,因為我們仍可以在函數體內修改指標的值,這並不是我們希望的,因此在此基礎上還需要 const 修飾指標的值。

下面是修改後的代碼:

void printArray(int const *const arr, size_t len) { ... }

指標常量與常量指標的關係#

我們會發現常量指標有兩種寫法:int const *const int *

對於第一種形式的理解:const向左修飾的,例如:int const *ptr;const 修飾的是 int 值類型,所以指標指向的值不可以修改;int *const ptr = nullptr;const 修飾 int * 指標類型,所以指標指向不能修改。這種理解需要遵守的代碼規範,因為如果將常量指標寫成 const int * 就需要我們進行轉換了。(也可以理解為如果左側沒有對象,則轉為修飾右側對象。)

常量指標指標常量的命名則是與 const int *int *const 的代碼規範相對應。

觀察以下代碼:

#include <iostream>

struct A {
    void foo() { std::cout << "non const" << std::endl; }
    void foo() const { std::cout << "const" << std::endl; }
};

int main() {
    A a;
    A *const ptr1 = &a;
    ptr1->foo();
    A const *ptr2 = &a;
    ptr2->foo();
}

int *const ptr1 = &aconst 修飾的是 ptr1 指標的值,沒有修飾指標所指向的對象,所以 ptr1->foo() 調用非 const 版本。

int const *ptr2 = &aconst 修飾的是 ptr2 指標指向的值 a,意思是指向的值不可修改,所以 ptr2->foo() 調用 const 版本。

如有紕漏,歡迎指正。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。