C++ V2 · MEMORY MODEL · 53
Vector / Reference / Pointer:先分清楚 Value、Object、Alias 與 Address
C++ 最容易卡住的地方,不是 * 或 & 長得奇怪,而是把「值」「物件」「別名」「位址」「lifetime」混成同一件事。這一課先用 vector 與 pass-by-reference 建立安全直覺,再進 pointer。
Learning outcomes
- 能解釋 vector 是 dynamic sequence,而不是「會自動長大的 array」這麼簡化。
- 區分 pass-by-value 與 pass-by-reference。
- 理解
&x取 address、int&宣告 reference、int*宣告 pointer、*ptrdereference。 - 能判斷 null、dangling、out-of-bounds 與 invalidated reference 的風險來源。
- 理解 const reference 為何是常見 read-only interface。
1. Why now:前兩課的 Score 讀完就消失
for (...) {
int score = 0;
std::cin >> score;
// after this iteration,
// score object dies
}
如果要之後算平均、排序或套 bonus,你需要一個 container 保存多筆資料。
2. Mental model:Vector 擁有一段可變長度的 Element Sequence
#include
std::vector scores = {
80,
90,
100
};
scores.push_back(95);
vector 管理自己的元素 storage 與 size/capacity。你應透過它的 interface 使用,不需要自己手動 new/delete 一塊 raw array。
3. Worked Example A:Pass-by-Value 會複製 Argument Value
void addFive(
int score
) {
score += 5;
}
int score = 80;
addFive(score);
std::cout << score;
// 80
callee 的 score 是另一個 local object。
4. Worked Example B:Reference 是 Existing Object 的 Alias
void addFive(
int& score
) {
score += 5;
}
int score = 80;
addFive(score);
std::cout << score;
// 85
caller object:
score = 80
parameter:
int& score
→ alias same object
modify parameter
→ caller object becomes 855. const Reference:Borrow without Copy, but no Mutation
double average(
const std::vector& scores
) {
if (scores.empty()) {
return 0.0;
}
int total = 0;
for (int score : scores) {
total += score;
}
return static_cast(
total
) / scores.size();
}
這個 interface 表達兩件事:不複製整個 vector;function 不應修改 caller 的 vector。
6. Worked Example C:Range-for 裡 Reference 決定你改的是 Copy 還是 Element
for (int score : scores) {
score += 5;
}
// vector unchanged
for (int& score : scores) {
score += 5;
}
// vector elements changed
第一段每輪 score 是 copy;第二段是 element alias。
7. Pointer:保存 Address 的 Value
int score = 90;
int* ptr =
&score;
std::cout << ptr;
std::cout << *ptr;
score object
↓ has address
&score
↓ store address
ptr
↓ dereference
*ptr
↓ access original object8. Reference 與 Pointer 不等於 Ownership
int score = 90;
int& ref = score;
int* ptr = &score;
這兩個都可以指向/存取現有 object,但它們不自動回答「誰負責 object 的 lifetime」。Ownership 會到 135 再正式處理。
9. nullptr:沒有指向 Valid Object
int* ptr = nullptr;
if (ptr != nullptr) {
std::cout << *ptr;
}
Dereference null pointer 是 undefined behavior。不要把「通常 crash」當成語言保證的唯一結果。
10. Dangling:Address 還留著,但 Object Lifetime 已結束
int* bad() {
int local = 10;
return &local;
}
function return 後 local object lifetime 結束;pointer 仍保存某個舊 address,但不再指向有效 object。
11. Vector Reallocation 也會影響 Reference / Pointer Validity
std::vector values = {
1,
2,
3
};
int& first =
values[0];
values.push_back(4);
// first may be invalidated
// if reallocation happened
Container mutation 可能使 references/pointers/iterators 失效。這不是 reference 語法本身壞,而是 underlying storage 移動。
12. Common mistakes
A. 把 & 當成固定一個意思
&x 是取 address;int& ref 是 reference declarator。
B. 把 raw pointer 當 ownership
它只保存 address-like value。
C. 以為 compile 成功代表 lifetime 安全
dangling 與 invalidation 常到 runtime 才爆。
D. 不必要地用 pointer
如果 value/reference 就能表達需求,不必為了「學 C++」硬用 raw pointer。
13. Debug evidence:Memory Bug 要先分類
null?
dangling?
out-of-bounds?
invalidated reference?
unexpected copy?
unexpected alias?
同樣是「值不對」,可能是 logic bug,也可能是 lifetime/alias 問題。先分類,再選工具。
14. Guided exercise:Bonus Function
void applyBonus(
std::vector& scores,
int bonus
) {
// TODO
}
要求修改 caller vector;每筆最多 100。再把 parameter 改成 pass-by-value,觀察 caller 是否改變。
15. Independent exercise:Read-only Summary
寫:
int passedCount(
const std::vector& scores
);
double average(
const std::vector& scores
);
不允許修改 vector;empty case 要有明確 contract。
16. Challenge:Reference Invalidation Experiment
建立 vector、保存某元素 address/reference、持續 push_back,觀察 capacity 改變時 address 是否變化。不要把觀察結果誤寫成所有實作都固定的保證;重點是理解 reallocation 可能 invalidation。
Project checkpoint:CLI Grade Analyzer · Memory Model v3
stdin
↓
std::vector
├─ average(const&)
├─ passedCount(const&)
└─ applyBonus(&)
↓
mutate elements
下一課會把「程式碼本身」放回完整 build pipeline:compile / link / executable / process。
17. Vocabulary / Summary
- object:有 storage/lifetime 的程式實體。
- reference:現有 object 的 alias。
- pointer:可保存 address 的 object/value。
- dereference:透過 pointer 存取指向 object。
- dangling:指向 lifetime 已結束 object 的 reference/pointer。
- invalidation:container operation 讓既有 iterator/reference/pointer 不再有效。
18. Further reading
Knowledge check · Mastery
- 區分 value copy、reference alias、pointer address。
- 完成 bonus / summary functions。
- 解釋 dangling 與 vector invalidation 的 root cause。
- 完成頁面下方 C++ memory-trace practice。