class: center, middle # CMPE 30: Lecture 11 Array and Vector Basics --- # What does this print? .lc[ ```cpp uint8_t a = 250; uint8_t b = 20; uint8_t sum = a + b; std::println("{}", sum); ``` ] .rc[ 1. 270 1. 255 1. 14 1. undefined behavior 1. Ben got this wrong ] --- # Learning Objectives - Use `std::array
` and explain why size is part of the type - Declare `std::vector
` with several construction styles - Add/remove elements with `push_back` / `pop_back` - Access with `[]`, `.at()`, `.front()`, `.back()` - Distinguish **size** from **capacity** - Clear and check a vector --- # The Trouble with C-Style Arrays - Do not know their own size - Decay to pointers when passed to functions - Cannot be returned - Cannot grow or shrink at runtime - Pass size separately and hope nothing goes out of bounds The standard library fixes all of this. --- # std::array .lc[ ```cpp #include
std::array
scores = {90, 85, 92, 88, 76}; std::cout << scores[0] << "\n"; // 90 std::cout << scores.at(1) << "\n"; // 85 std::cout << scores.size() << "\n";// 5 ``` ] .rc[ - Size is part of the type - `std::array
` and `std::array
` are different types - `.size()` is `constexpr` - `[]` fast, `.at()` safe ] --- # Passing std::array to Functions .lc[ ```cpp void print_scores( const std::array
&scores) { for (size_t i = 0; i < scores.size(); i++) std::cout << scores[i] << "\n"; } ``` ] .rc[ - The function knows the size --- no extra parameter - Size is a compile-time constant **Trap:** You cannot write `std::array
` where `n` is a variable. Use `std::vector` for runtime sizes. ] --- # std::vector .lc[ ```cpp #include
std::vector
empty; std::vector
zeros(5); std::vector
fives(5, 42); std::vector
songs = {"Wannabe", "No Diggity"}; ``` ] .rc[ - Dynamic size; grows as needed - The workhorse container of C++ - Multiple construction styles - Use it for almost everything ] --- # push_back and pop_back .lc[ ```cpp std::vector
playlist; playlist.push_back("Wannabe"); playlist.push_back("No Diggity"); std::cout << playlist.size(); // 2 playlist.pop_back(); std::cout << playlist.size(); // 1 ``` ] .rc[ - `push_back` adds one to the end - `pop_back` removes the last element (does **not** return it) **Trap:** `pop_back()` on an **empty** vector is undefined behavior. Check `.empty()` first. ] --- # Accessing Elements .lc[ ```cpp std::vector
bands = {"Spice Girls", "Blackstreet", "Oasis"}; bands[0]; // Spice Girls (fast) bands.at(1); // Blackstreet (checked) bands.front(); // Spice Girls bands.back(); // Oasis ``` ] .rc[ - `[]` fast, no bounds check - `.at()` throws on bad index - `.front()` / `.back()` are convenient shortcuts ] --- # Size vs Capacity .lc[ ```cpp std::vector
v; for (int i = 0; i < 5; i++) { v.push_back(i * 10); std::cout << "size=" << v.size() << " cap=" << v.capacity() << "\n"; } ``` ] .rc[ - `.size()` --- how many elements - `.capacity()` --- how much is allocated - Capacity grows in **jumps** (typically doubling) - `push_back` is **amortized** O(1) ] --- # Capacity Growth Typical output: ``` size=1 cap=1 size=2 cap=2 size=3 cap=4 size=4 cap=4 size=5 cap=8 ``` - When capacity is exhausted, a bigger block is allocated and everything is copied - Mostly fast, occasionally does extra work --- # empty and clear .lc[ ```cpp if (v.empty()) { /* size() == 0 */ } v.clear(); // size -> 0 ``` ] .rc[ - `.empty()` returns `true` for size 0 - `.clear()` removes all elements **Wut:** After `clear()`, `.size()` is 0 but `.capacity()` is **unchanged**. Memory is kept for future use. ] --- # What does this print? .lc[ ```cpp std::vector
v = {10, 20, 30}; v.push_back(40); v.pop_back(); v.pop_back(); std::cout << v.size() << " " << v.back() << "\n"; ``` ] .rc[ 1. `3 30` 1. `2 20` 1. `2 30` 1. `4 30` 1. Ben got this wrong ] --- # What does this print? .lc[ ```cpp std::vector
v = {1, 2, 3}; v.clear(); std::cout << v.size() << " " << v.empty() << "\n"; ``` ] .rc[ 1. `0 0` 1. `0 1` 1. `3 0` 1. `3 1` 1. Ben got this wrong ] --- # Key Points - `std::array` is compile-time sized; `std::vector` is runtime-sized - `[]` is fast, `.at()` is safe - Vector capacity grows in **jumps**; `.clear()` keeps the memory - Never `pop_back` an empty vector **Read:** chapter 8, remaining sections --- insert/erase/reserve, range-based `for`, iterators, `auto`. **Do:** exercises 4, 6, 7, 9, 11, 12.