HOWTO · C++

在 C++ 中從指向向量的指標訪問成員函式

了解如何在 C++ 中透過指標呼叫 std::vector 成員、將向量指標傳遞給函式,以及遍歷其元素。

本頁內容

若要透過指標呼叫 C++ 向量的成員,請使用 ptr->member;等效寫法是 (*ptr).member。指標必須指向向量物件本身。先用 & 取得該物件的位址,再用其中一種寫法存取 size() 和 at() 等成員。下方範例也會將指標傳給函式,並透過它讀取每個值。

使用 -> 透過指標存取向量

宣告指標時,在向量型別後加上 *。若是整數向量,型別就是 std::vector<int>*。假設 values 是已存在的向量,&values 就是它的位址;將位址指定給指標後,指標便會指向該向量。這不會複製向量,也不會建立另一個集合。

箭號運算子會結合指標解參照與選取成員這兩個操作。因此,ptr->size() 會呼叫 ptr 所指向向量的 size()。也可以將同一個指標傳給參數型別相符的函式。在完整範例中,report_size 接收指向 const 向量的指標,因為它只會讀取向量。const 限定會防止函式透過該參數修改向量,但不會改變指標的傳遞方式。

執行此範例:

#include <cstddef>
#include <iostream>
#include <vector>

void report_size(const std::vector<int>* ptr) {
    std::cout << "Count: " << ptr->size() << '\n';
}

int main() {
    std::vector<int> values{10, 20, 30};
    const std::vector<int>* ptr = &values;

    report_size(ptr);
    for (std::size_t i = 0; i < ptr->size(); ++i) {
        std::cout << (*ptr).at(i) << '\n';
    }
}
Count: 3
10
20
30

執行後會先印出向量大小,再將每個值各自印在一行。向量是自動儲存期的區域變數,而指標只會在向量仍位於作用域內時使用。在自己的程式中,請確保指標的生命週期不會超過它所儲存位址之物件的生命週期。

使用 (*ptr).member 透過指標存取向量

運算式 (*ptr).member 會先解參照 ptr,取得向量物件,再用 . 選取該物件的成員。括號不可省略:若沒有括號,. 會在解參照之前先套用到 ptr,這不是預期的操作。存取向量成員時,(*ptr).size() 和 ptr->size() 的意思相同。箭號寫法較簡短;解參照後接點號的寫法則清楚呈現這兩個操作。

在上方範例中,(*ptr).at(i) 會先解參照向量指標,再依索引存取元素。成員函式仍是由向量呼叫,而 at(i) 會傳回所選取的整數。理解這項差異有助於閱讀程式碼:ptr 的型別是指向向量的指標,但 (*ptr).at(i) 取得的是元素值。若函式需要處理整個向量,請傳入指向向量的指標;若只需要一個元素,則應使用元素參考或適當的元素指標。

透過指向向量的指標逐一走訪元素

迴圈以 ptr->size() 作為停止條件,並透過 (*ptr).at(i) 存取每個值。這兩個操作都是透過指向向量的指標進行。索引成員呼叫也可以寫成箭號形式 ptr->at(i);它會選取相同的向量成員。從 <cstddef> 引入的 std::size_t 是無號型別,適合用來表示向量大小及索引。

向量指標與向量迭代器、指向單一元素的指標並不相同。此範例中的指標指向整個 std::vector<int> 物件。迭代器是容器提供、用來逐步走訪元素的位置;元素指標則指向其中一個儲存的值。使用索引的迴圈能清楚區分這些角色,並適合需要索引的情況。如果只需要逐一造訪所有值,也可以對 *ptr 使用範圍型迴圈;不過,那是在走訪向量本身,並非每一步都透過指標示範成員存取。

由於範例在走訪期間不會修改向量,因此依索引存取相當直接。如果程式在走訪時插入或移除元素,就應重新檢視迴圈:這些操作可能改變向量大小,也可能使指向元素的參考、指標或迭代器失效。指向向量物件的指標仍會指向該物件,但它不會讓元素位置保持穩定。每次使用指標時都要確保向量仍然存在,並選擇能配合程式中任何變更的走訪方式。