CS โ std map followup
๐ 04/30 โ std::map ๋ชจ์๋ฉด์ ๊ผฌ๋ฆฌ์ง๋ฌธ ์ ๋ฆฌ
14_std_map.md๋ชจ์๋ฉด์ ์งํ ๋์จ ํ์ ์ง๋ฌธ 10๊ฐ๋ฅผ 1:1๋ก ์ ๋ฆฌํ ๋ ธํธ. ๋ณธ๋ฌธ์ 14๋ฒ ์๋ณธ์ ํด๋น ์น์ ์ ๊ฐ๋ฆฌํค๊ณ , ์ฌ๊ธฐ์๋ ๋ต๋ณ๋ง ์งง๊ฒ ๊ฒฐ๋ก โ ๊ทผ๊ฑฐ โ ์ฝ๋/์ ์์ผ๋ก ์์ถํ๋ค.
๋ชฉ์ฐจ
- ํด์ ์ถฉ๋๋ก ์ธํ O(n) ์คํ์ดํฌ ํํผ
- compare ์ฌ์ ์ (Custom Compare)
- ํด์ / unordered / ์ค๋ณตํค ํ์ฉ
- Red-Black Tree ์ red ๊ท์น
- AVL ์ฝ์
- emplace ๊ฐ ๋ญ๊ฐ
- ํ(heap) ์ด ๋ญ๊ฐ
- Red โ ์ ๋ ธ๋๋ฅผ ๋นจ๊ฐ์ผ๋ก ์ฝ์ ํ๋ ๊ธฐ์ค
- ์ธ๋ฆฌ์ผ์ด ์บ์ ์นํ ์ฐ์ ์ธ ์ด์
- Algo:: ๊ฐ ๋ญ์ง
1. ํด์ ์ถฉ๋๋ก ์ธํ O(n) ์คํ์ดํฌ ํํผ
ํ ์ค ๊ฒฐ๋ก โ std::unordered_map ์ ํ๊ท O(1) ์ด์ง๋ง ์
์์ ์
๋ ฅ / ๋์ ํด์ ํจ์๋ก ๋ชจ๋ ํค๊ฐ ํ ๋ฒํท์ ๋ชฐ๋ฆฌ๋ฉด O(n) ๊น์ง ๋จ์ด์ง๋ค. ์ด โ์ต์
๋ณด์ฅโ์ด ํ์ํ๋ฉด std::map (RB-Tree, O(log n) ์ต์
๋ณด์ฅ) ์ ์ ํํ๋ค.
1
2
3
4
5
// ์
์์ ํด์ โ ๋ชจ๋ ํค๊ฐ bucket[0] ์ ์ฒด์ธ
struct BadHash { size_t operator()(int k) const { return 0; } };
std::unordered_map<int, int, BadHash> u;
for (int i = 0; i < 1000; ++i) u.insert({i, i});
u.find(999); // O(n) โ 1000๋ฒ ๋น๊ต
์ธ์ map ์ ์ ํ?
- ์ค์๊ฐ ์์คํ ยท์๋ฒ ๋ฑ ๊ผฌ๋ฆฌ ์ง์ฐ(tail latency) ์ด ์ค์
- ์ธ๋ถ ์ ๋ ฅ ํค(ํด๋ผ๊ฐ ๋ณด๋ธ ID, URL ๋ฑ) โ ํด์ DoS ๋ฐฉ์ด
- ํค ์ ๋ ฌยท๋ฒ์ ์กฐํ(
lower_bound/upper_bound) ๊ฐ ๋์์ ํ์
std::map์ ํ์ + ์ฌ์์น ๋ก ํธ๋ฆฌ ๋์ด๋ฅผ ํญ์โค 2 logโ(n+1)๋ก ๋ฌถ์ด ์ต์ ๋ O(log n) ๋ณด์ฅ. 14๋ฒ ยง3-2 ์ฐธ์กฐ.
2. compare ์ฌ์ ์ (Custom Compare)
ํ ์ค ๊ฒฐ๋ก โ std::map ์ 3๋ฒ์งธ ํ
ํ๋ฆฟ ์ธ์๊ฐ Compare (๊ธฐ๋ณธ std::less<Key>). ์ด ์๋ฆฌ๋ฅผ ํจ์ ๊ฐ์ฒด / ๋๋ค / ํจ์ ํฌ์ธํฐ๋ก ๋ฐ๊ฟ ์ ๋ ฌ ๊ธฐ์ค์ ๊ฐ์๋ ์ ์๋ค. ํค ๊ฐ์ฒด๊ฐ operator< ๋ฅผ ๊ฐ์ง๋ฉด ๋ณ๋ ์์
์์ด ๋์.
2-1. ์๊ทธ๋์ฒ
1
2
3
4
template<class Key, class T,
class Compare = std::less<Key>,
class Allocator = std::allocator<std::pair<const Key, T>>>
class map;
2-2. ๋ด๋ฆผ์ฐจ์ (std::greater)
1
2
3
std::map<int, std::string, std::greater<int>> desc;
desc[1]="one"; desc[2]="two"; desc[3]="three";
// ์ํ: 3 โ 2 โ 1
2-3. ๋๋ค (๋์๋ฌธ์ ๋ฌด์ ์ ๋ ฌ)
1
2
3
4
5
6
auto ci_less = [](const std::string& a, const std::string& b) {
return std::lexicographical_compare(
a.begin(), a.end(), b.begin(), b.end(),
[](char ca, char cb){ return std::tolower(ca) < std::tolower(cb); });
};
std::map<std::string, int, decltype(ci_less)> m(ci_less);
2-4. ์ฌ์ฉ์ ์ ์ ํค โ operator< ๋ง ์ ์ํ๋ฉด ๋
1
2
3
4
5
6
7
struct Point {
int x, y;
bool operator<(const Point& o) const {
return std::tie(x, y) < std::tie(o.x, o.y); // lexicographic
}
};
std::map<Point, std::string> places; // Compare ์ธ์ ์๋ต
ํธ๋ฆฌ๋งต์
operator<ํ๋๋ก ์ถฉ๋ถ. ํด์๋งต์std::hash<K>ํน์ํ +operator==๋ ๋ค ํ์ โ ํธ๋ฆฌ๋งต์ ์์ ํธ์์ฑ.
3. ํด์ / unordered / ์ค๋ณตํค ํ์ฉ
3-1. โํด์ = unorderedโ ์ธ ์ด์
ํด์ ํ
์ด๋ธ์ hash(key) % bucket_count โ ๋ฒํท ์ธ๋ฑ์ค๋ก ๋งคํํ๋ค. ํค โ ์ ์ โ ์ฌ๋กฏ. ์ ์ ๋ชจ๋๋ก ๊ฒฐ๊ณผ๋ ํค ์๋ณธ ์์์ ๋ฌด๊ดํ๋ฏ๋ก, ์ํ ์์๋ฅผ ๋ณด์ฅํ ๋ฐฉ๋ฒ์ด ์๋ค. ๊ทธ๋์ STL ๋ ์ด๋ฆ์ unordered_ ๋ฅผ ๋ถ์๋ค.
1
2
3
4
ํค: "Alice", "Bob", "Carol"
ํด์: hash("Alice")=4283..., hash("Bob")=8821..., hash("Carol")=5512...
๋ฒํท: 4283 % 16 = 11, 8821 % 16 = 5, 5512 % 16 = 8
์ํ: bucket[5]=Bob โ bucket[8]=Carol โ bucket[11]=Alice โ ํค ์ฌ์ ์ X
3-2. ๊ฒ์ ํ๋ก๊ทธ๋๋ฐ์ด unordered ๋ฅผ ์ ํธํ๋ ์ด์
14๋ฒ ยง9 + 13๋ฒ ๊ฒฐ๋ก ๊ณผ ๋์ผ โ ์บ์ ์นํยทํ๊ท O(1)
| ๊ฒ์ ์ํฌ๋ก๋ | ํธ๋ฆฌ(map) | ํด์(unordered_map / TMap) |
|---|---|---|
| ๋งค ํ๋ ์ 1000~10000 lookup | log n ร ์บ์ ๋ฏธ์ค ๋น์ธ๋ค | ํ๊ท 1๋ฒ hit, ์บ์ ์นํ |
| ํค ์ ๋ ฌ ๊ฑฐ์ ์ ์ | ๊ฐ์ ๋ฌด์ฉ | ์์ค ์์ |
| ์ต์ ๋ณด์ฅ vs ํ๊ท ์ฒ๋ฆฌ๋ | ์ต์ ๋ณด์ฅ | ํ๊ท ์ฒ๋ฆฌ๋ โ โ |
| ๋ฉ๋ชจ๋ฆฌ ์ง์ญ์ฑ | ๋ ธ๋ ๋ถ์ฐ(ํ) | ์ฌ๋กฏ ๋ฐฐ์ด ์ธ์ |
Unreal TMap ์ ๋ ๋์๊ฐ ์ฒด์ด๋ ๋์ open addressing ์ ์จ์ ์บ์ ์นํ์ฑ์ ํ ๋จ๊ณ ๋ ์ฌ๋ ธ๋ค (14๋ฒ ยง9-6).
3-3. โํด์์ผ ๋ ์ค๋ณตํค ํ์ฉ?โ
| ๋จ์ผ ํค | ์ค๋ณต ํค |
|---|---|
std::unordered_map<K,V> | std::unordered_multimap<K,V> |
std::unordered_set<K> | std::unordered_multiset<K> |
Unreal TMap<K,V> | Unreal TMultiMap<K,V> |
- ๋จ์ผ ํค ์ปจํ ์ด๋๋ ์ค๋ณต ๋ถ๊ฐ โ ํด์์ด๋ ํธ๋ฆฌ์ด๋ ๋์ผ.
- ์ค๋ณต์ ํ์ฉํ๋ ค๋ฉด
multi*/TMultiMap์ ๋ช ์์ ์ผ๋ก ์ ํ. - ์ค๋ณต ์
equal_range(STL) /MultiFind(Unreal) ๋ก ๊ฐ์ ํค์ ๋ชจ๋ ๊ฐ์ ๋ฌถ์ด ๊ฐ์ ธ์ด.
1
2
3
4
5
std::unordered_multimap<std::string, int> scores;
scores.insert({"Alice", 85});
scores.insert({"Alice", 92});
scores.insert({"Alice", 78});
auto [from, to] = scores.equal_range("Alice");
C++11 ์ดํ
multi*์ปจํ ์ด๋๋ ์ฝ์ ์์ ์์ ์ฑ(stability) ๋ ๋ณด์ฅ โ ๊ฐ์ ํค ์์์ ๋จผ์ ๋ฃ์ ๊ฒ ๋จผ์ ๋์จ๋ค.
4. Red-Black Tree ์ red ๊ท์น
ํ ์ค ๊ฒฐ๋ก โ RB-Tree ์ ์๊น์ 5๊ฐ์ง ์์ฑ์ ๋์์ ๋ง์กฑํด์ผ ํ๋ค. ๋นจ๊ฐ์ ๊ทธ์ค 4๋ฒ(์ฐ์ ๊ธ์ง)๊ณผ 5๋ฒ(black height ์ผ์ ) ์ ํต์ฌ ๋ณ์.
1
2
3
4
5
1) ๋ชจ๋ ๋
ธ๋๋ ๋นจ๊ฐ ๋๋ ๊ฒ์
2) ๋ฃจํธ๋ ๊ฒ์
3) ๋ชจ๋ NIL (๋ฆฌํ) ์ ๊ฒ์
4) ๋นจ๊ฐ ๋
ธ๋์ ์์์ ๋ฐ๋์ ๊ฒ์ โ ๋นจ๊ฐ ์ฐ์(R-R) ๊ธ์ง
5) ์์ ๋
ธ๋ โ ํ์ NIL ๊น์ง ๊ฒฝ๋ก์ ๊ฒ์ ๋
ธ๋ ์ ๋์ผ (black height)
4-1. โredโ ๋ง ๋ฐ๋ก ๋ณด๋ฉด ๋ ๊ฐ์ง ๊ท์น
- R-R ๊ธ์ง (์์ฑ 4) โ ๋นจ๊ฐ ๋ ๊ฐ๊ฐ ๋ถ๋ชจ-์์์ผ๋ก ์ด์ด์ง๋ฉด ์๋ฐ. ์ฝ์ ยท์ญ์ ํ ํ์ ยท์ฌ์์น ๋ก ์ฆ์ ๋ณต๊ตฌ.
- ์ฝ์ ์ ์ ๋ ธ๋ = ๋นจ๊ฐ (๊ดํ) โ ๊ฒ์ ์ผ๋ก ๋ฃ์ผ๋ฉด black height ๊ฐ ๊นจ์ ธ ๋ณต๊ตฌ๊ฐ ๋ ๋น์ธ๋ค โ ํญ์ ๋นจ๊ฐ. ์์ธํ ์ด์ ๋ ยง8.
4-2. R-R ์๋ฐ ๋ณต๊ตฌ ํ๋ฆ (์ฝ์ )
1
2
3
๋ถ๋ชจ๊ฐ ๊ฒ์ โ ๋ (์๋ฐ ์์)
๋ถ๋ชจ๊ฐ ๋นจ๊ฐ + ์ผ์ด๋ ๋นจ๊ฐ โ ์ฌ์์น (ํ ์๋ฒ์ง ๋นจ๊ฐ, ์๋ก ์ ํ)
๋ถ๋ชจ๊ฐ ๋นจ๊ฐ + ์ผ์ด์ด ๊ฒ์ โ ํ์ + ์ฌ์์น (LL/LR/RR/RL 4์ผ์ด์ค)
์ฝ์ ์ ํ์ ์ ์ต๋ 2ํ, ์ญ์ ์ ์ต๋ 3ํ๋ก ๋๋๋ค (14๋ฒ ยง3-3, ยง3-4).
5. AVL ์ฝ์
Adelson-Velsky and Landis โ 1962๋ RB ํธ๋ฆฌ๋ณด๋ค ๋จผ์ ๊ณ ์ํ ์๊ธฐ ๊ท ํ BST. ๋ฐ๋ช ์ ๋ ์ฌ๋์ ์ด๋ฆ์ ๊ทธ๋๋ก ๋๋ค.
| ย | RB-Tree | AVL Tree |
|---|---|---|
| ๊ท ํ ์กฐ๊ฑด | ์๊น 5์์ฑ | ๋ชจ๋ ๋ ธ๋ ์ข์ฐ ๋์ด ์ฐจ โค 1 |
| ํธ๋ฆฌ ๋์ด | โค 2 log(n+1) | โค 1.44 log(n+2) |
| ๊ฒ์ | ์ฝ๊ฐ ๋๋ฆผ | ์ฝ๊ฐ ๋น ๋ฆ |
| ์ฝ์ ํ์ | ์ต๋ 2ํ | ์ต๋ 1ํ์ง๋ง ์๋ก ์ ํ |
| ์ญ์ ํ์ | ์ต๋ 3ํ | ์ต๋ O(log n) ํ |
| ๋ฉ๋ชจ๋ฆฌ | ์ 1๋นํธ | ๋์ด ์ ๋ณด ~4B |
| ์ฑํ์ฒ | STL map/set, Linux CFS, Java TreeMap | DB ์ธ๋ฑ์ค(์ ํต) |
์๊ธฐ ํจํด: ๊ฒ์ โซ ๊ฐฑ์ โ AVL / ๊ฐฑ์ ๋ ์์ฃผ โ RB / ๋ฒ์ฉ โ RB. STL ์ด RB ๋ฅผ ์ ํํ ์ด์ ๋ โ๊ฐฑ์ ๋ ํํ ๋ฒ์ฉ ์ปจํ ์ด๋โ ๋ผ์.
6. emplace ๊ฐ ๋ญ๊ฐ
ํ ์ค ๊ฒฐ๋ก โ emplace(args...) ๋ ์ปจํ
์ด๋์ ๋
ธ๋ ์์์ ์ง์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค. ์์ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ง ์์ผ๋ฏ๋ก ๋ณต์ฌ/์ด๋ ๋น์ฉ์ ์ค์ด๊ณ , ๋ฌด๋ธ-์จ๋ฆฌ ํ์
(unique_ptr) ๋ ๊น๋ํ ๋ด์ ์ ์๋ค.
6-1. insert / emplace / operator[] ๋น๊ต
1
2
3
4
5
6
7
8
9
10
std::map<std::string, std::vector<int>> m;
// 1) operator[] โ default ์์ฑ ํ ๋์
(2๋จ๊ณ)
m["A"] = std::vector<int>{1,2,3};
// 2) insert โ ์์ pair ์์ฑ
m.insert({"B", std::vector<int>{4,5,6}});
// 3) emplace โ pair ์ธ์๋ฅผ ๋ฐ์ ๋
ธ๋ ์์์ in-place ์์ฑ โ
m.emplace("C", std::vector<int>{7,8,9});
6-2. C++17 ์ ๋ ํ์
| ํจ์ | ํค ์์ ๋ | ํค ์์ ๋ | ํน์ง |
|---|---|---|---|
emplace(k, args...) | ๋ฌด์ (์ธ์๋ ์ด๋ฏธ ํ๊ฐ๋จ) | ๋ ธ๋ in-place ์์ฑ | ํ์ค emplace |
try_emplace(k, args...) | ์ธ์ ์์ฒด๋ฅผ ๋ง๋ค์ง ์์ โ | ๋ ธ๋ in-place ์์ฑ | unique_ptr ์์ |
insert_or_assign(k, v) | ๊ธฐ์กด ๊ฐ์ ๋์ | ์๋ก ์ฝ์ | ์๋ ๋ช ํ (operator[] ํธ๋ฉ ํํผ) |
6-3. try_emplace + unique_ptr ํจํด
1
2
3
4
5
6
7
8
std::map<std::string, std::unique_ptr<Resource>> resources;
// operator[] ํจ์ : ์ด๋ฏธ ์์ผ๋ฉด ๊ธฐ์กด unique_ptr ํ๊ดด
resources["key1"] = std::make_unique<Resource>("data1");
// try_emplace: ํค ์์ผ๋ฉด make_unique ํธ์ถ์กฐ์ฐจ ์ ํจ โ
auto [it, inserted] = resources.try_emplace("key1",
std::make_unique<Resource>("data1"));
๋ฉด์ ๋จ๊ณจ โ โoperator[] ์ emplace ์ฐจ์ด?โ โ ์์ ๊ฐ์ฒด + default ์ฝ์ ํธ๋ฉ โ try_emplace / insert_or_assign ์ผ๋ก ์ ๋ฆฌ. 14๋ฒ ยง7-4ยทยง7-5 ์๋ณธ.
7. ํ(heap) ์ด ๋ญ๊ฐ
๋ฉด์ ๋งฅ๋ฝ์ ๋ฐ๋ผ ๋ ๊ฐ์ง ์๋ฏธ๊ฐ ์์ด๋ฏ๋ก ํญ์ ๋ ๋ค ๋ตํด ๋๋ค.
7-1. ๋ฉ๋ชจ๋ฆฌ ์์ญ์ผ๋ก์์ ํ
| ์์ญ | ํ ๋น ์์ | ํด์ ์์ | ๋น๊ณ |
|---|---|---|---|
| ์คํ | ํจ์ ์ง์ | ํจ์ ์ข ๋ฃ (RAII) | ๋น ๋ฆ, ํฌ๊ธฐ ์ ํ |
| ํ(heap) | new / malloc | delete / free | ๋๋ฆผ, ํฌ๊ธฐ ํผ, ๋จํธํ |
| ์ ์ /์ ์ญ | ํ๋ก๊ทธ๋จ ์์ | ์ข ๋ฃ | static, ์ ์ญ ๋ณ์ |
std::map / std::list / std::unordered_map ์ด ๋
ธ๋๋ฅผ ํ์ ๋ถ์ฐ ํ ๋น ํ๋ ์ด์ โ ๋
ธ๋ ํฌ๊ธฐ๊ฐ ๊ฐ๋ณ์ด๊ณ , iterator ์์ ์ฑ์ ์ํด ๋
ธ๋ ์ฃผ์๊ฐ ๊ณ ์ ๋ผ์ผ ํ๊ธฐ ๋๋ฌธ. ๊ทธ ๋๊ฐ๋ก ์บ์ ์ ๋์ .
1
2
3
std::map<int,int> m;
// ๋
ธ๋ 1๊ฐ โ color(8) + parent(8) + left(8) + right(8) + pair(int+int+pad)(12) + heap header(~16)
// โ 60๋ฐ์ดํธ โ ๋ฐ์ดํฐ 8B ์ํด 60B โ ํจ์จ ~13%
7-2. ์๋ฃ๊ตฌ์กฐ๋ก์์ ํ
๋ถ๋ชจ โฅ ์์(max-heap) / ๋ถ๋ชจ โค ์์(min-heap) ์ธ ์์ ์ด์ง ํธ๋ฆฌ. STL std::priority_queue ์ ๋ด๋ถ ๊ตฌ์กฐ์ด๋ฉฐ ๋ณดํต std::vector ๋ฐฐ์ด ์์ ์ธ๋ฑ์ค๋ก ํํ (์บ์ ์นํ).
| ์ฐ์ฐ | ๋ณต์ก๋ |
|---|---|
| push | O(log n) |
| pop (top ์ ๊ฑฐ) | O(log n) |
| top | O(1) |
๊ฒ์์์๋ A* ๊ธธ์ฐพ๊ธฐ์ open list, ์ด๋ฒคํธ ํ์ด๋จธ ํ, ์ฐ์ ์์ ์์ ํ ๋ฑ์ ์ฐ์.
8. Red โ ์ ๋ ธ๋๋ฅผ ๋นจ๊ฐ์ผ๋ก ์ฝ์ ํ๋ ๊ธฐ์ค
ํ ์ค ๊ฒฐ๋ก โ black height ๋ณํ๋ฅผ 0์ผ๋ก ๋ง๋ค๊ธฐ ์ํด์. ๊ฒ์ ์ผ๋ก ๋ฃ์ผ๋ฉด ๊ทธ ๊ฒฝ๋ก black height ๊ฐ 1 ๋์ด ์์ฑ 5(๋ชจ๋ ๊ฒฝ๋ก ๊ฒ์ ์ ๋์ผ) ๊ฐ ๊นจ์ง๊ณ , ๋ค๋ฅธ ๋ชจ๋ ๊ฒฝ๋ก๋ฅผ ๋ง์ถฐ์ผ ํด์ ๋น์ธ๋ค. ๋นจ๊ฐ์ผ๋ก ๋ฃ์ผ๋ฉด ์๋ฐ ๊ฐ๋ฅ์ฑ์ ์์ฑ 4(R-R ๊ธ์ง) ํ ๊ฐ์ง๋ก ๊ตญํ๋๊ณ ํ์ ยท์ฌ์์น ๋ก ๊ตญ์ ๋ณต๊ตฌ๋๋ค.
1
2
3
4
5
6
7
8
9
๊ฒ์ ์ฝ์
์:
โ ๊ทธ ๊ฒฝ๋ก black height +1
โ ์์ฑ 5 ์๋ฐ (๋ชจ๋ ๊ฒฝ๋ก์ black height ๋์ผํด์ผ ํจ)
โ ๋ค๋ฅธ ๋ชจ๋ ๊ฒฝ๋ก์๋ black height ๋ง์ถ๊ธฐ โ ์ ์ฒด ํธ๋ฆฌ ์๋ด์ผ ํจ
๋นจ๊ฐ ์ฝ์
์:
โ black height ๋ณํ ์์ (์์ฑ 5 ์ ์ง)
โ ์๋ฐ ๊ฐ๋ฅ์ฑ์ ์์ฑ 4 (R-R) ๋ฟ
โ ๋ถ๋ชจ๊ฐ ๊ฒ์ ์ด๋ฉด ๋, ๋นจ๊ฐ์ด๋ฉด ํ์ ยท์ฌ์์น ๋ก ๊ตญ์ ๋ณต๊ตฌ
๋ณต๊ตฌ ๋ถ๊ธฐ (์ฝ์ ํ):
1
2
3
parent.color == BLACK โ ๋
parent.color == RED, uncle == RED โ ์ฌ์์น (ํ ์๋ฒ์ง ๋นจ๊ฐ, ์๋ก ์ ํ)
parent.color == RED, uncle == BLACK โ ํ์ + ์ฌ์์น (LL/LR/RR/RL)
์ฝ์ ์ ํ์ ์ ์ต๋ 2ํ โ RB ๊ฐ AVL ๋ณด๋ค ๊ฐฑ์ ๋น์ฉ์ด ์ ์ ๊ฒฐ์ ์ ์ด์ .
9. ์ธ๋ฆฌ์ผ์ด ์บ์ ์นํ ์ฐ์ ์ธ ์ด์
ํ ์ค ๊ฒฐ๋ก โ ๊ฒ์ ์์ง์ ๋งค ํ๋ ์ 16.6ms (60fps) / 8.3ms (120fps) ๋ผ๋ ์ ๋ ์๊ฐ ์์ฐ์ด ์๊ณ , ๊ฐ์ ์๋ฃ์ ๋ํด ์๋ง ๋ฒ lookupยทiterate ๊ฐ ์ผ์ด๋๋ค. ํธ๋ฆฌยท์ฐ๊ฒฐ ๋ฆฌ์คํธ์ ๋ ธ๋ ๋ถ์ฐ์ ์บ์ ๋ฏธ์ค๋ฅผ ์์ฐํด frame budget ์ ๊ฐ์๋จน๋๋ค.
9-1. 1๊ธ ์๋ฏผ ์ปจํ ์ด๋
| ์นดํ ๊ณ ๋ฆฌ | STL | Unreal | ๋น๊ณ |
|---|---|---|---|
| ์ํ์ค | std::vector | TArray โ
| ์ฐ์ ๋ฐฐ์ด |
| ํด์ ๋งต | std::unordered_map | TMap โ
| open addressing (์ฒด์ด๋ X) |
| ํด์ ์ | std::unordered_set | TSet โ
| ย |
| ์ ๋ ฌ ๋งต (RB-Tree) | std::map | (์์) | TSortedMap ์ผ๋ก ๋์ฒด |
| ์ฐ๊ฒฐ ๋ฆฌ์คํธ | std::list | TLinkedList (๋ณด์กฐ) | ๊ฑฐ์ ์ ์ |
9-2. TSortedMap ๋ RB ๊ฐ ์๋๋ค
๋ด๋ถ๋ ์ ๋ ฌ๋ TArray + ์ด์ง ํ์. ์์ N ์์๋ RB-Tree ๋ณด๋ค ์บ์ ์นํ์ ์ด๊ณ , ํฐ N ์์๋ ํธ๋ฆฌ ๋
ธ๋ 60B/์์ 8B ๊ฐ์ ์ค๋ฒํค๋๋ฅผ ํผํ๋ค.
9-3. TMap ์ open addressing
std::unordered_map ์ ์ถฉ๋ ์ ๋
ธ๋๋ฅผ next ํฌ์ธํฐ๋ก ์ฒด์ด๋ โ ๋
ธ๋๊ฐ ํ์ ๋ถ์ฐ. TMap ์ ๋ฒํท ์ฌ๋กฏ ๋ฐฐ์ด์์ ๋ค์ ์ฌ๋กฏ์ผ๋ก probing โ ์ธ์ ๋ฉ๋ชจ๋ฆฌ hit ์ผ๋ก ์บ์ ์นํ.
9-4. UPROPERTY / GC ํตํฉ
1
2
3
4
5
6
7
UCLASS()
class AInventory : public AActor {
GENERATED_BODY()
public:
UPROPERTY()
TMap<FName, UItem*> Items; // GC ๊ฐ value UObject ์๋ ์ถ์
};
std::map<FName, UItem*> ์ GC ๊ฐ ์ถ์ ๋ชป ํด ์ธ๋ฆฌ์ผ์์๋ ์ ๋ ์ฌ์ฉ X. ์บ์ ์นํ + GC ํตํฉ ๋ ๊ฐ์ง๊ฐ TMap/TArray/TSet ์ 1๊ธ ์๋ฏผ์ผ๋ก ๋ง๋ ์ด์ .
13๋ฒ์์ ๋ณธ
std::listํํผ, 14๋ฒ์์ ๋ณธstd::mapํํผ โ โ๋ถ์ฐ ๋ ธ๋ ์๋ฃ๊ตฌ์กฐ ํํผโ ๊ฐ ์ผ๊ด๋ ๊ฒ์ ์์ง ์ฒ ํ.
10. Algo:: ๊ฐ ๋ญ์ง
ํ ์ค ๊ฒฐ๋ก โ Unreal ์ ์๊ณ ๋ฆฌ์ฆ ๋ค์์คํ์ด์ค. STL <algorithm> ์ std::sort / std::find / std::binary_search ๋ฑ๊ณผ 1:1 ๋์๋๋ ํจ์๋ค์ด Algo:: ์๋ ์๋ค. TArray ์์์ STL ์๊ณ ๋ฆฌ์ฆ๊ณผ ๊ฐ์ ํจํด์ผ๋ก ์ ๋ ฌยทํ์ยท๋ณํ์ ์ํํ๋ค.
10-1. ์์ฃผ ์ฐ๋ ํจ์
| Algo:: | STL ๋์ | ์ฉ๋ |
|---|---|---|
Algo::Sort | std::sort | ๋น๊ต ์ ๋ ฌ (introsort) |
Algo::StableSort | std::stable_sort | ์์ ์ ๋ ฌ |
Algo::BinarySearch | std::binary_search | ์ ๋ ฌ๋ ๋ฐฐ์ด ํ์ |
Algo::BinarySearchBy | (lambda ํค ์ถ์ถ) | ํค ์ถ์ถ ๋๋ค๋ก ํ์ |
Algo::Find | std::find | ์ ํ ํ์ |
Algo::FindBy | std::find_if | ์ ์ด ํ์ |
Algo::Reverse | std::reverse | ๋ค์ง๊ธฐ |
Algo::Transform | std::transform | ์ฌ์ |
Algo::Accumulate | std::accumulate | ๋์ |
Algo::AllOf / AnyOf / NoneOf | ๋๋ช STL | ์ ์ด ๊ฒ์ฌ |
10-2. ์ฝ๋ ์ โ TArray ์ ๋ ฌ + ์ด์ง ํ์
1
2
3
4
5
6
7
8
9
10
11
12
TArray<TPair<FString, int32>> Pairs;
Pairs.Add({"Alice", 30});
Pairs.Add({"Bob", 25});
// ํค ๊ธฐ์ค ์ ๋ ฌ
Algo::Sort(Pairs, [](const auto& A, const auto& B){
return A.Key < B.Key;
});
// ํค ์ถ์ถ ๋๋ค๋ก ์ด์ง ํ์
auto Idx = Algo::BinarySearchBy(Pairs, FString("Alice"),
[](const auto& P){ return P.Key; });
10-3. TArray::Sort ์ ์ฐจ์ด
TArray::Sort() ๋ ๋ฉค๋ฒ ํจ์๋ก ๊ฐ์ ์ผ์ ํ๋ค. Algo:: ๋ ์์์ range/iterator ํ์ด๋ฅผ ๋ฐ๋ ์์ ํจ์๋ผ STL ์คํ์ผ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ข๊ณ , TArray ๊ฐ ์๋ ๋ค๋ฅธ ์ปจํ
์ด๋์๋ ์ธ ์ ์๋ค.
์ ๋ ฌ๋
TArray+Algo::BinarySearchBy= ์ฌ์ค์TSortedMap์ ๋ด๋ถ ๊ตฌ์กฐ. 14๋ฒ ยง9-7 ์๋ณธ.
11. ํด์(Hash) ๊ฐ ๋ญ๊ฐ / ๋ฒํท(Bucket) ์ด ๋ญ๊ฐ
ํ ์ค ๊ฒฐ๋ก โ ํด์ ํจ์๋ ์์์ ํค(๋ฌธ์์ดยท์ ์ยท๊ตฌ์กฐ์ฒด)๋ฅผ ๊ณ ์ ํฌ๊ธฐ ์ ์๋ก ๋ฐ๊พธ๋ ํจ์. ๋ฒํท์ ํด์๊ฐ์ผ๋ก ์ธ๋ฑ์ฑ๋๋ ์ฌ๋กฏ(๋ฐฐ์ด ์นธ). ํด์ํ
์ด๋ธ์ ๋ฒํท = hash(key) % bucket_count ํ ์ค๋ก ํคโ์ฌ๋กฏ ๋งคํ์ ๋ง๋ ๋ค.
11-1. ํด์ ํจ์์ 3๊ฐ์ง ์๊ฑด
| ์๊ฑด | ์๋ฏธ | ์๋ฐ ์ |
|---|---|---|
| ๊ฒฐ์ ์ฑ | ๊ฐ์ ํค โ ํญ์ ๊ฐ์ ํด์๊ฐ | find ๊ฐ ๋ง๊ฐ์ง |
| ๊ท ๋ฑ ๋ถํฌ | ํค๋ค์ด ์ ์ ๊ณต๊ฐ์ ๊ณจ๊ณ ๋ฃจ ํฉ๋ฟ๋ ค์ง | ์ถฉ๋ ํญ์ฆ โ O(n) |
| ๋น ๋ฆ | O(1) ์ ๊ฐ๊น๊ฒ ๊ณ์ฐ | ํ๊ท O(1) ๊นจ์ง |
1
2
3
4
5
6
7
8
9
10
// std::hash ํน์ํ โ ์ฌ์ฉ์ ์ ์ ํ์
์ ํด์ ๋ถ์ฌ
struct Point { int x, y; };
namespace std {
template<> struct hash<Point> {
size_t operator()(const Point& p) const noexcept {
return hash<int>{}(p.x) ^ (hash<int>{}(p.y) << 1);
}
};
}
std::unordered_map<Point, int> m; // ์ด์ ์ฌ์ฉ ๊ฐ๋ฅ
11-2. ๋ฒํท = ํด์ ํ ์ด๋ธ์ ์ฌ๋กฏ
1
2
3
4
5
6
7
ํค: "Alice" "Bob" "Carol"
hash(): 4283950122 8821445190 5512330847
% 16: 11 5 8
โ โ โ
buckets[16] = [_, _, _, _, _, Bob, _, _, Carol, _, _, Alice, _, _, _, _]
โ โ โ
bucket 5 bucket 8 bucket 11
bucket_countโ ๋ฒํท ๋ฐฐ์ด ํฌ๊ธฐ (๋ณดํต 2์ ๊ฑฐ๋ญ์ ๊ณฑ์ด๋ ์์ ๊ทผ์ฒ)bucket(key)โ ํค๊ฐ ๋ค์ด๊ฐ๋ ๋ฒํท ์ธ๋ฑ์ค ๋ฐํ (u.bucket("Alice")โ 11)bucket_size(n)โ n๋ฒ ๋ฒํท์ ๋ด๊ธด ์์ ์ (์ถฉ๋ ์ง๋จ์ฉ)
11-3. ์ถฉ๋ = ๋ค๋ฅธ ํค๊ฐ ๊ฐ์ ๋ฒํท
1
2
hash("foo") % 16 = 5
hash("xyz") % 16 = 5 โ ๋ค๋ฅธ ํค์ธ๋ฐ ๊ฐ์ ๋ฒํท โ ์ถฉ๋
ํด๊ฒฐ ๋ฐฉ๋ฒ ๋ ๊ฐ์ง:
| ๋ฐฉ์ | ๋์ | STL | Unreal |
|---|---|---|---|
| Separate Chaining | ๊ฐ์ ๋ฒํท ์์๋ฅผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ก ๋ฌถ์ | std::unordered_map | (์ ์) |
| Open Addressing | ์ถฉ๋ ์ ๋ค์ ๋น ์ฌ๋กฏ์ผ๋ก probing | (์ ์) | TMap โ
|
์ฒด์ด๋์ ๋
ธ๋๊ฐ ํ์ ๋ถ์ฐ โ ์บ์ ์ ๋์ . open addressing ์ ๊ฐ์ ๋ฐฐ์ด ์์์ ๋ค์ ์ฌ๋กฏ โ ์บ์ ์นํ. ๊ทธ๋์ TMap ์ด std::unordered_map ๋ณด๋ค ๊ฒ์์์ ๋น ๋ฅด๋ค (14๋ฒ ยง9-6).
11-4. ์ข์ ํด์ ํจ์์ ์กฐ๊ฑด
1
2
3
4
5
6
7
// ๋์ ํด์ โ ๋ชจ๋ ์ ์๊ฐ ๊ฐ์ ๊ฐ
struct BadHash { size_t operator()(int) const { return 42; } };
// โ ๋ชจ๋ ํค๊ฐ bucket[42 % N] ํ ๊ณณ์ ๋ชฐ๋ฆผ โ O(n)
// ์ข์ ํด์ โ ๊ท ๋ฑ ๋ถํฌ + ๋น ๋ฆ
// std::hash<int> ๋ ๋ณดํต ํญ๋ฑํจ์์ ๊ฐ๊น๊ณ (k ์์ฒด)
// std::hash<std::string> ์ FNV-1a / MurmurHash ๋ฑ ์ฌ์ฉ
์ ์์ ์ ๋ ฅ์ด ๊ฐ๋ฅํ ํ๊ฒฝ(์น ์๋ฒ) ์์๋ Java/Python ์ฒ๋ผ SipHash ๊ฐ์ cryptographic ํด์๋ก DoS ๋ฐฉ์ด. C++ ํ์ค์ ๋ช ์ ์ ํจ.
12. unordered_map ์ load_factor ์๊ณ ์ด๊ณผ โ ์ธ์ ์ผ์ด๋๋
ํ ์ค ๊ฒฐ๋ก โ load_factor() = size / bucket_count ๊ฐ max_load_factor()(๊ธฐ๋ณธ 1.0) ๋ฅผ ๋๋ ์๊ฐ rehash ๋ฐ์. ์ฆ ์์ ์ > ๋ฒํท ์ ๊ฐ ๋๋ ๋ค์ insert/emplace ํธ์ถ ๋.
12-1. ์๊ณ ์กฐ๊ฑด
1
2
3
4
5
6
7
8
std::unordered_map<int,int> u;
// ๊ธฐ๋ณธ max_load_factor = 1.0
// ์ด๊ธฐ bucket_count ๋ ๊ตฌํ ์ ์ (๋ณดํต 1 ๋๋ 0)
u.insert({1, 100});
// ๋ง์ฝ bucket_count == 1 ์ด๊ณ size == 1 ์ด๋ฉด load_factor == 1.0
// ๋ค์ insert ์์ 1.0 ์ด๊ณผ ์์ โ rehash
u.insert({2, 200}); // โ
rehash ๋ฐ์ (bucket_count 2๋ฐฐ ํ์ฅ)
๊ธฐ๋ณธ max_load_factor ๋ 1.0 โ ํ๊ท ๋ฒํท 1๊ฐ๋น ์์ 1๊ฐ๋ฅผ ์ ์งํ๋ ค๋ ์ ์ฑ . ๋ ๋นก๋นกํ๊ฒ ํ๋ฉด ๋ฉ๋ชจ๋ฆฌ + ์ถฉ๋ โ, ๋ ๋์จํ๊ฒ ํ๋ฉด ๋ฉ๋ชจ๋ฆฌ ์ ์ฝํ์ง๋ง ์ถฉ๋ยท์ฒด์ธ ๊ธธ์ด โ.
12-2. rehash ๋์ (size > bucket_count ๊ฐ ๋ ์งํ insert)
1
2
3
4
5
1) ์ ๋ฒํท ๋ฐฐ์ด ํ ๋น (๋ณดํต 2๋ฐฐ ํฌ๊ธฐ, ์์ ๊ทผ์ฒ๋ก ๋ฐ์ฌ๋ฆผ)
2) ๋ชจ๋ ์์๋ฅผ hash(key) % new_bucket_count ๋ก ๋ค์ ๋ถ๋ฐฐ
3) ๊ธฐ์กด ๋ฒํท ๋ฐฐ์ด ํด์
๋น์ฉ: O(n) โ 13๋ฒ vector ์ฌํ ๋น๊ณผ ๋์ผ ํจํด
๋ถ์ ํจ๊ณผ: ๋ชจ๋ iteratorยทํฌ์ธํฐยท์ฐธ์กฐ ๋ฌดํจํ โ
12-3. ํธ๋ฆฌ๊ฑฐ ์์ ์ ๋ฆฌ
| ์ํฉ | rehash? |
|---|---|
insert ํ size <= bucket_count ร max_load_factor | X |
insert ํ size > bucket_count ร max_load_factor | O โ |
erase (์์ ์ญ์ ) | ์๋ rehash ์์ |
u.rehash(n) ๋ช
์ ํธ์ถ | bucket_count โฅ n ๋ณด์ฅ์ผ๋ก ์ฆ์ |
u.reserve(n) ๋ช
์ ํธ์ถ | size n ๊น์ง rehash ์ ์ผ์ด๋๋๋ก ์ฌ์ ํ๋ณด |
max_load_factor(0.5) ๋ก ๋ฎ์ถค | ๋ค์ insert ๋ถํฐ ๋ ์ผ์ฐ ๋ฐ๋ |
12-4. ํํผ ํจํด
1
2
3
4
5
6
7
8
9
10
std::unordered_map<int,int> u;
u.reserve(10000); // ๋ฏธ๋ฆฌ ์ถฉ๋ถํ ๋ฒํท ํ๋ณด โ 10000 ๊น์ง rehash 0ํ
for (int i = 0; i < 10000; ++i)
u.insert({i, i}); // ํ ๋ฒ๋ rehash ์์
// โ ์ํฐ ํจํด โ ๋ฃจํ ๋์ค iterator ๋ณด๊ด
auto it = u.insert({1, 100}).first;
for (int i = 0; i < 10000; ++i)
u.insert({i, i}); // โ
๋์ค์ rehash โ it ๋ฌดํจ โ UB
ํด์๋งต์์ iterator ๋ฅผ ๊ธธ๊ฒ ๋ค๊ณ ๋ค๋์ง ๋ง ๊ฒ โ rehash ํ ๋ฒ์ ์ ๋ถ ๋ฌดํจ. RB-Tree ๊ธฐ๋ฐ std::map ์ ์ฝ์
์ ๋ฌดํจํ ์์ (๋
ธ๋ ์์ ์ฑ).
13. map ์์ โ๋ ธ๋โ ๋ ๋ญ ๊ฐ๋ฆฌํค๋
ํ ์ค ๊ฒฐ๋ก โ std::map ์ ๋
ธ๋๋ ํ์ ํ ๋น๋ RB-Tree ๋
ธ๋ 1๊ฐ ์ด๋ฉฐ, ์์ ์๊น + ๋ถ๋ชจ/์ข/์ฐ ํฌ์ธํฐ 3๊ฐ + std::pair<const Key, T> 1๊ฐ ๊ฐ ๋ค์ด ์๋ค. iterator ๋ ์ด ๋
ธ๋์ ์ฃผ์๋ฅผ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ๋ค.
13-1. ๋ ธ๋ ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์ (libstdc++ ๋จ์ํ)
1
2
3
4
5
6
7
struct _Rb_tree_node {
_Rb_tree_color color; // R or B (1๋ฐ์ดํธ์ง๋ง ์ ๋ ฌ๋ก 4~8B)
_Rb_tree_node* parent; // ๋ถ๋ชจ 8B
_Rb_tree_node* left; // ์ผ์ชฝ ์์ 8B
_Rb_tree_node* right; // ์ค๋ฅธ์ชฝ ์์ 8B
std::pair<const Key, T> data; // ํค-๊ฐ ์ โ ์ฌ์ฉ์ ๋ฐ์ดํฐ
};
std::map<int,int> ๋
ธ๋ 1๊ฐ โ
1
2
3
์(8) + parent(8) + left(8) + right(8) + (ํค 4 + ๊ฐ 4 + pad 4) + heap header(~16)
= 60๋ฐ์ดํธ
โ ๋ฐ์ดํฐ 8B ์ํด 60B โ ํจ์จ ~13%
13-2. ๋ ธ๋๋ ํ์ ๋ถ์ฐ ํ ๋น
1
2
3
4
5
6
7
m.insert({1, "a"}); // ๋
ธ๋ A ๋ฅผ new ๋ก ํ ํ ๋น
m.insert({2, "b"}); // ๋
ธ๋ B ๋ฅผ new ๋ก ํ ํ ๋น (A ์ ๋ฉ๋ชจ๋ฆฌ์ ์ธ์ ๋ณด์ฅ X)
m.insert({3, "c"}); // ๋
ธ๋ C ...
ํ: โโโโโโโ โโโโโโโ โโโโโโโ
โ A=1 โ โโ โ B=2 โ โโ โ C=3 โ โ ํธ๋ฆฌ ํฌ์ธํฐ๋ก ์ฐ๊ฒฐ, ๋ฉ๋ชจ๋ฆฌ๋ ํฉ์ด์ง
โโโโโโโ โโโโโโโ โโโโโโโ
์ด ๋ถ์ฐ์ด ๋ ธ๋ ์์ ์ฑ ์ ์์ฒ โ ํ ๋ ธ๋ ์ด๋/์ญ์ ๊ฐ ๋ค๋ฅธ ๋ ธ๋ ์ฃผ์์ ์ํฅ ์์. ๋์์ ์บ์ ์ ๋์ ์ ์์ธ์ด๊ธฐ๋ ํจ (vector ์ ์ ๋ฐ๋).
13-3. iterator ๊ฐ ๊ฐ๋ฆฌํค๋ ๊ฒ
1
2
3
4
auto it = m.find(2);
// it ๋ ๋
ธ๋ B ์ ํฌ์ธํฐ (์ ํํ๋ _Rb_tree_iterator<pair<const int,int>>)
// it->first == 2 โ ๋
ธ๋ B ์ data.first
// it->second == "b" โ ๋
ธ๋ B ์ data.second
- iterator ์ฆ๊ฐ (
++it) โ RB-Tree ์ in-order successor ๋ก ์ด๋ โ ์ ๋ ฌ ์ ๋ค์ ๋ ธ๋ - ์ญ์ ๋ ๋ ธ๋์ iterator ๋ง ๋ฌดํจํ, ๋๋จธ์ง๋ ์์ โ ๋ ธ๋ ์์ ์ฑ
13-4. ๋ ธ๋ โ ๋ค๋ฅธ ์ปจํ ์ด๋ ๋น๊ต
| ์ปจํ ์ด๋ | ๋ ธ๋๋? | ๋ฉ๋ชจ๋ฆฌ ์์น | iterator ์์ ์ฑ |
|---|---|---|---|
std::vector<T> | ๋ ธ๋ ๊ฐ๋ ์์ | ์ฐ์ ๋ฐฐ์ด | ์ฌํ ๋น ์ ๋ชจ๋ ๋ฌดํจ |
std::list<T> | prev + next + T | ํ ๋ถ์ฐ | ๋งค์ฐ ์์ |
std::map<K,V> | color + parent/left/right + pair | ํ ๋ถ์ฐ | ์ฝ์ ๋ฌดํจ X, ์ญ์ ๋ ๋ณธ์ธ๋ง |
std::unordered_map<K,V> | next + pair (์ฒด์ด๋ ๋ ธ๋) | ํ ๋ถ์ฐ + ๋ฒํท ๋ฐฐ์ด | rehash ์ ๋ชจ๋ ๋ฌดํจ |
โmap ์์ ๋ ธ๋๋ ํธ๋ฆฌ ๋ ธ๋, vector ์์ ์์๋ ๋ฐฐ์ด ์นธโ โ ๋ ธ๋ ๋จ์ ์๋ฃ๊ตฌ์กฐ๋ ํญ์ ํ์ ํฉ๋ฟ๋ ค์ ธ ์บ์ ์นํ์ฑ์ ์๋ ๋๊ฐ๋ก iterator ์์ ์ฑ๊ณผ ๊ฐ๋ณ ์ฝ์ /์ญ์ O(log n) ์ ์ป๋๋ค.
14. ํ = ๋ฉ๋ชจ๋ฆฌ ํ ๋น ์์ ์ด์ผ๊ธฐ์ธ๊ฐ?
๋ถ๋ถ ์ ๋ต โ ํ์ โ๋์ ํ ๋น์ด ์ผ์ด๋๋ ๋ฉ๋ชจ๋ฆฌ ์์ญโ ์ด์ง ์์ ์์ฒด๋ ์๋๋ค. โํ ๋น ์์ ์ด ๋ฐํ์โ ์ด๋ผ๋ ๊ฒ ํ์ ํน์ง์ด๊ณ , ๊ทธ ๊ฒฐ๊ณผ๊ฐ โ์๋ช ์ ํ๋ก๊ทธ๋๋จธ๊ฐ ์ ์ดํ๋คโ ๋ ์์ ์์ ๋๋ค.
14-1. ๋ ์์ + ๋ ์์ญ
1
2
3
4
5
๊ตฌ๋ถ | ์์ญ | ํ ๋น ์์ | ํด์ ์์
โโโโโโโโโโโโโ|โโโโโโโโโ|โโโโโโโโโโโโโโโโโโ|โโโโโโโโโโโโโโโโโโ
์ ์ /์ ์ญ | data/bss | ์ปดํ์ผ/ํ๋ก๊ทธ๋จ ์์ | ํ๋ก๊ทธ๋จ ์ข
๋ฃ
์ง์ญ ๋ณ์ | ์คํ | ํจ์ ์ง์
(๋ฐํ์) | ํจ์ ์ข
๋ฃ (์๋, RAII)
new / malloc | ํ | ๋ฐํ์ (์์ฒญ ์ฆ์) | delete/free ํธ์ถ ์ โ
| ย | ์คํ | ํ |
|---|---|---|
| ์์ | ํจ์ ์ง์ ์ ์๋ | ๋ฐํ์ new ํธ์ถ ์ |
| ํด์ | ํจ์ ์ข ๋ฃ ์ ์๋ | delete ๋ช
์ ํธ์ถ (๋๋ ์ค๋งํธ ํฌ์ธํฐ) |
| ์๋ | ๋งค์ฐ ๋น ๋ฆ (SP ์ด๋) | ๋๋ฆผ (ํ ๋น์ ์๊ณ ๋ฆฌ์ฆ) |
| ํฌ๊ธฐ | ์์ (~MB) | ํผ (~GB) |
| ๋จํธํ | ์์ | ์์ |
| ์๋ช | ์ค์ฝํ ํ์ | ํ๋ก๊ทธ๋๋จธ ์ ์ด |
14-2. ๊ทธ๋์ ํ = ์์ ์ธ๊ฐ, ์์ญ์ธ๊ฐ?
์๋ฐํ๊ฒ๋ ์์ญ. ๋ค๋ง โ์ ํ์ ์ฐ๋๊ฐ?โ ์ ๋ต์ด ๊ณง ์์ ์ด์ผ๊ธฐ๋ค:
- ๊ฐ์ฒด์ ์๋ช ์ ํจ์ ์ค์ฝํ ๋ฐ์ผ๋ก ์ฐ์ฅํด์ผ ํ๋ค
- ๊ฐ์ฒด ํฌ๊ธฐ๊ฐ ์ปดํ์ผ ํ์์ ์ ํด์ง์ง ์๋๋ค (๋ฐํ์ ์ ๋ ฅ์ ๋ฐ๋ผ)
- ๊ฐ์ฒด๊ฐ ๋๋ฌด ์ปค์ ์คํ ํ๊ณ๋ฅผ ๋๋๋ค
์ด ์ธ ๊ฐ์ง๊ฐ ์ถฉ์กฑ๋๋ฉด ํ. ๊ทธ๋์ ํ์ โ๋ฐํ์ ๋์ ํ ๋น์ ์์ญโ ์ด๋ผ๊ณ ์ค์ฌ ๋ถ๋ฅด๊ณ , ํํ์์๋ โํ ๋น ์์ โ ์ผ๋ก ํตํ๊ธฐ๋ ํ๋ค.
14-3. STL ์ปจํ ์ด๋์ ํ ์ฌ์ฉ
| ์ปจํ ์ด๋ | ํ ์ฌ์ฉ ํจํด |
|---|---|
std::vector<T> | ๋ฐ์ดํฐ ๋ฐฐ์ด 1๊ฐ๋ฅผ ํ์ ํ ๋น, ์ฌํ ๋น ์ ์ ๋ฐฐ์ด + ๋ณต์ฌ |
std::list<T> | ๋ ธ๋ 1๊ฐ์ฉ ๋ฐ๋ก ํ ํ ๋น (๋ถ์ฐ) |
std::map<K,V> | ๋ ธ๋ 1๊ฐ์ฉ ๋ฐ๋ก ํ ํ ๋น (๋ถ์ฐ) |
std::unordered_map<K,V> | ๋ฒํท ๋ฐฐ์ด 1๊ฐ + ๋ ธ๋๋ค (์ฒด์ด๋) ๋ชจ๋ ํ |
๊ฒ์ ์์ง์ด TArray ๋ฅผ 1๊ธ ์๋ฏผ์ผ๋ก ๋๋ ๊ฑด, ํ ํ ๋น ํ์ ์์ฒด๋ฅผ ์ค์ด๋ ๊ฒ ๋ ๋ชฉ์ ์ด๋ค. ๋
ธ๋ 1๋ง ๊ฐ๋ฅผ ํ์ 1๋ง ๋ฒ new ํ๋ ๊ฒ๋ณด๋ค ๋ฐฐ์ด 1๊ฐ๋ก ํฐ ๋ธ๋ก ํ ๋ฒ ํ ๋น์ด ํจ์ฌ ๋น ๋ฅด๊ณ ์บ์ ์นํ์ .
14๋ฒ ยง3-6 ๋ ธ๋ ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์ + 11๋ฒ ์ค๋งํธ ํฌ์ธํฐ(ํ ์๋ช ์๋ํ) ์ ๋ฌถ์ด ํจ๊ป ๋ตํ๋ฉด ๊น์ด๊ฐ ์ฐ๋ค.
15. ํด์ = ๋ฉ๋ชจ๋ฆฌ ํ ๋น ์ ํ์ํ ์ ์๊ฐ?
ํ ์ค ๊ฒฐ๋ก โ ์๋๋๋ค. ํด์๋ ํ ๋น๊ณผ ๋ฌด๊ดํ๋ค. ํด์๋ ์ด๋ฏธ ํ ๋น๋ ๋ฒํท ๋ฐฐ์ด์์ โ์ด๋ ์ฌ๋กฏ์ ์ธ์ง ์ธ๋ฑ์ฑโ ํ๋ ์ ์๊ฐ์ด๋ค. ๋ฉ๋ชจ๋ฆฌ๋ new/malloc ์ด ์ก๊ณ , ํด์๋ ๊ทธ ์์์ ์์น๋ง ๊ฒฐ์ ํ๋ค.
15-1. ๋ ๊ฐ์ง๋ฅผ ๋ถ๋ฆฌ
| ๋จ๊ณ | ๋๊ฐ ํ๋๊ฐ | ๊ฒฐ๊ณผ |
|---|---|---|
| ๋ฉ๋ชจ๋ฆฌ ํ ๋น | new / malloc (ํ ํ ๋น์) | ๋ฒํท ๋ฐฐ์ด์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์ ํ๋ณด |
| ์์น ๊ฒฐ์ | ํด์ ํจ์ | โ์ด ํค๋ buckets[11] ์ ๋ฃ์โ |
1
2
3
4
5
6
std::unordered_map<std::string, int> u;
u.reserve(16); // โ ํ ๋น โ ํ์ 16์นธ์ง๋ฆฌ ๋ฒํท ๋ฐฐ์ด ๋ง๋ จ (ํด์ ๋ฌด๊ด)
u["Alice"] = 30; // โก ์์น ๊ฒฐ์ โ hash("Alice") % 16 = 11 โ buckets[11] ์ ์ ์ฅ
// ^^^^^^^^^^^^^^^^^^
// ์ฌ๊ธฐ๊ฐ ํด์. ํ ๋น์ด ์๋๋ผ ์ธ๋ฑ์ฑ.
15-2. ํด์์ ์ ํํ ์ ์
ํด์ = ํค๋ฅผ ์ ์ ๊ณต๊ฐ์ ๋งคํํ๋ ํจ์์ ๊ฒฐ๊ณผ๊ฐ. ๊ทธ ์ ์๋ฅผ ๋ชจ๋๋ก ์ฐ์ฐํด ๋ฒํท ์ธ๋ฑ์ค๋ก ์ด๋ค.
1
2
3
4
"Alice" โโhash()โโโถ 4283950122 โโ% bucket_countโโโถ 11
โ โ
ํด์๊ฐ ๋ฒํท ์ธ๋ฑ์ค
(ํ ๋น ์๋) (๋ฐฐ์ด ์ฒจ์)
15-3. ๋น์ โ ๋์๊ด ์ฑ ์ฅ
1
2
๋ฉ๋ชจ๋ฆฌ ํ ๋น = "16์นธ์ง๋ฆฌ ์ฑ
์ฅ์ ์ฌ์ ๋์๊ด์ ๋๋๋ค" โ ํ ๋ฒ
ํด์ = "์ด ์ฑ
์ ISBN ๋์๋ฆฌ ๋ณด๊ณ 11๋ฒ ์นธ์ ๊ฝ์" โ ์ฑ
๋ง๋ค
์ฑ ์ฅ(๋ฒํท ๋ฐฐ์ด) ์ ์ด๋ฏธ ์๊ณ , ํด์๋ ์ ์ฑ ์ ์ด๋ ์นธ์ ๊ฝ์์ง / ์ฐพ์ ์ฑ ์ด ์ด๋ ์นธ์ ์๋์ง ์๋ ค์ค ๋ฟ. ์ฑ ์ฅ์ ์ฌ๊ฑฐ๋ ๋๋ฆฌ๋(rehash) ์ผ์ ํด์๊ฐ ์๋๋ผ ํ ๋น์๊ฐ ํ๋ค.
15-4. ์์ ์ ๋ฆฌ
| ์์ | ์ผ์ด๋๋ ์ผ | ํด์ ์ฌ์ฉ? |
|---|---|---|
unordered_map ์์ฑ | ์ด๊ธฐ ๋ฒํท ๋ฐฐ์ด ํ ๋น | X (ํ ๋น์๋ง) |
insert(k, v) | hash(k) % N โ ๋ฒํท ๊ฒฐ์ โ ๋ ธ๋ ์ฝ์ | O |
find(k) | hash(k) % N โ ๋ฒํท ๊ฒฐ์ โ ๋น๊ต | O |
| load_factor ์ด๊ณผ | ์ ๋ฒํท ๋ฐฐ์ด ํ ๋น + ๋ชจ๋ ์์ ์ฌ๋ฐฐ์น | O (์ฌ๋ฐฐ์น ์ ๋ชจ๋ ํค hash ์ฌ๊ณ์ฐ) |
erase(k) | hash(k) % N โ ๋ฒํท ๊ฒฐ์ โ ๋ ธ๋ ์ ๊ฑฐ | O |
ํด์๋ insert/find/erase ๊ฐ ์ผ์ด๋ ๋๋ง๋ค ํค๋ง๋ค 1ํ์ฉ ํธ์ถ๋๋ค. ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ ์ปจํ ์ด๋ ์์ฑยทrehash ๊ฐ์ ๋๋ฌธ ์ฌ๊ฑด์์๋ง ์ผ์ด๋จ. ๋ ์ฌ๊ฑด์ ๋น๋๋ถํฐ ๋ค๋ฅด๋ค.
15-5. ๊ทธ๋ผ โํ ๋น ์ ํ์ํ ์ ์โ ๋ ๋ญ๊ฐ ์๋?
์ง๋ฌธ์ ์ง๊ด๊ณผ ๊ฐ์ฅ ๊ฐ๊น์ด ๊ฑด ํฌ์ธํฐ ๊ฐ (= ๋ฉ๋ชจ๋ฆฌ ์ฃผ์). new T ๋ ํ์์ ๋น ์์ญ์ ์ฐพ์ ๊ทธ ์์ญ์ ์์ ์ฃผ์(์ ์) ๋ฅผ ๋ฐํํ๋ค.
1
2
int* p = new int(42);
// p ์ ๊ฐ = 0x7ffd1c00abc0 โ ์ด๊ฒ "ํ ๋น ์ ๋ฐ๋ ์ ์"
ํด์๊ฐ๊ณผ ํฌ์ธํฐ๊ฐ์ ๋ ๋ค ์ ์์ง๋ง ์๋ฏธ๊ฐ ๋ค๋ฅด๋ค:
| ย | ํด์๊ฐ | ํฌ์ธํฐ๊ฐ |
|---|---|---|
| ์ถ์ฒ | ํด์ ํจ์๊ฐ ํค๋ก๋ถํฐ ๊ณ์ฐ | ํ ๋น์๊ฐ ๋น ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ์ฐพ์ ๋ฐํ |
| ์ฉ๋ | ๋ฒํท ๋ฐฐ์ด์ ์ธ๋ฑ์ค | ๋ฉ๋ชจ๋ฆฌ์ ์ฃผ์ |
| ๊ฒฐ์ ์ฑ | ๊ฐ์ ํค โ ๊ฐ์ ํด์ (ํ์ ) | ๊ฐ์ ํธ์ถ๋ ๋งค๋ฒ ๋ค๋ฅธ ์ฃผ์ (๋นํ์ ) |
| ๋ฒ์ | [0, bucket_count) ๋ก ๋ชจ๋๋ก | ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ ์ ์ฒด |
15-6. ์ ์ ๋ ํ ์ค ์ ์
ํด์๋ โํค โ ๋ฒํท ์ธ๋ฑ์คโ ๋ณํ์ ์ฐ๋ ์ ์๊ฐ์ด์ง, ๋ฉ๋ชจ๋ฆฌ ํ ๋น๊ณผ๋ ๋ฌด๊ด. ํ ๋น์ ํ ๋น์(
new/malloc) ์ ์ผ์ด๊ณ , ํด์๋ ์ด๋ฏธ ํ ๋น๋ ๋ฒํท ๋ฐฐ์ด ์์์ ์์น๋ง ๊ฒฐ์ ํ๋ค.
ยง11 (ํด์ยท๋ฒํท) + ยง14 (ํ = ์์ญ) ๋ฅผ ๋ฌถ์ด์ ๋ณด๋ฉด, โํ ๋น์๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ก๊ณ โ ๊ทธ ์์์ ํด์๋ก ์ฌ๋กฏ์ ๊ณ ๋ฅธ๋คโ ๋ ๋ ๋จ๊ณ๊ฐ ๊น๋ํ๊ฒ ๋ถ๋ฆฌ๋๋ค.
16. ํด์๋ ํฌ์ธํฐ ์ฃผ์๊ฐ ๊ฐ์ ๊ฑด๊ฐ?
ํ ์ค ๊ฒฐ๋ก โ ์๋๋๋ค. ๋ ๋ค ์ ์์ง๋ง ์ถ์ฒยท์ฉ๋ยท๊ฒฐ์ ์ฑ์ด ์ ๋ฐ๋๋ค. ํฌ์ธํฐ๋ ํ ๋น์๊ฐ ์ก์ ์ค ๋ฉ๋ชจ๋ฆฌ ์ฃผ์ (๊ทธ๊ณณ์ ๊ฐ๋ฉด ๋ฐ์ดํฐ๊ฐ ์๋ค), ํด์๋ ํค๋ก๋ถํฐ ๊ณ์ฐํ ์ธ๋ฑ์ค ์ฌ๋ฃ (๋ฐฐ์ด์ ๋ช ๋ฒ ์นธ์ ์ธ์ง). ํท๊ฐ๋ฆฌ๋ฉด ๋ฉด์ ์์ ๊นจ์ง๋ค.
16-1. ๊ฒฐ์ ์ ์ฐจ์ด โ โ์ด๋์ ์ค๋๊ฐโ
1
2
3
4
5
6
7
8
9
10
11
ํฌ์ธํฐ ์ฃผ์๊ฐ:
int* p = new int(42);
// ํ ๋น์(OS/ํ ๋น์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ)๊ฐ ๋น ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ์ฐพ์ ๊ทธ ์ฃผ์๋ฅผ ๋ฐํ
// โ p == 0x7ffd1c00abc0 ๊ฐ์ ๊ฐ์ ์ฃผ์
// โ ๊ฐ์ ์ฝ๋ ๋ ๋ฒ ์คํํ๋ฉด ๋งค๋ฒ ๋ค๋ฅธ ๊ฐ (ASLR + ํ ์ํ์ ๋ฐ๋ผ)
ํด์๊ฐ:
size_t h = std::hash<std::string>{}("Alice");
// ํด์ ํจ์๊ฐ ํค ์์ฒด๋ก๋ถํฐ ๊ณ์ฐ
// โ h == 4283950122 (์์)
// โ ๊ฐ์ ํค "Alice" ๋ ๊ฐ์ ํ๋ก์ธ์ค์์ ํญ์ ๊ฐ์ ๊ฐ โ
16-2. ๋น๊ตํ (์ด๋ฒ ์ง๋ฌธ ํต์ฌ)
| ์์ฑ | ํฌ์ธํฐ ์ฃผ์๊ฐ | ํด์๊ฐ |
|---|---|---|
| ๋๊ฐ ๋ง๋๋ | ํ ๋น์ (new/malloc) | ํด์ ํจ์ (std::hash<K>) |
| ๋ฌด์์ผ๋ก๋ถํฐ | ๋น์ด์๋ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ์ฐพ์ | ํค์ ๋ด์ฉ์ผ๋ก๋ถํฐ ๊ณ์ฐ |
| ์๋ฏธ | โ์ฌ๊ธฐ ๊ฐ๋ฉด ๋ฐ์ดํฐ๊ฐ ์๋คโ (์ฐธ์กฐ) | โ์ด ํค๋ N๋ฒ ์นธ์ ๋ฃ์ด๋ผโ (์ธ๋ฑ์ค ์ฌ๋ฃ) |
| ๊ฒฐ์ ์ฑ | ๊ฐ์ ํธ์ถ๋ ๋งค๋ฒ ๋ค๋ฆ (๋น๊ฒฐ์ ์ ) | ๊ฐ์ ํค โ ํญ์ ๊ฐ์ ๊ฐ (๊ฒฐ์ ์ ) โ |
| ์ญ์ฐธ์กฐ ๊ฐ๋ฅ? | *p ๋ก ๋ฐ์ดํฐ ์ ๊ทผ ๊ฐ๋ฅ | ์ญ์ฐธ์กฐ ๋ถ๊ฐ โ ๊ทธ๋ฅ ์ ์ |
| ์ ํจ์ฑ | ํ ๋น๋ ๋ฉ๋ชจ๋ฆฌ ํ์ . delete ํ ๋๊ธ๋ง | ํญ์ ์ ํจ (์์ ํจ์ ๊ฒฐ๊ณผ) |
| ์ถฉ๋ ๊ฐ๋ฅ? | ๋ ๊ฐ์ฒด๊ฐ ๊ฐ์ ์ฃผ์? โ ๋ถ๊ฐ๋ฅ | ๋ ํค๊ฐ ๊ฐ์ ํด์? โ ๊ฐ๋ฅ (์ถฉ๋) |
| ๋ฒ์ | ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ ์ ์ฒด (~64๋นํธ ํ ๋ฒ์) | size_t ์ ์ (๋ชจ๋๋ก ํ [0, bucket_count)) |
16-3. ๊ฐ์ฅ ๊ฒฐ์ ์ ์ธ ํ ๊ฐ์ง โ ๊ฒฐ์ ์ฑ
1
2
3
4
5
6
7
8
9
10
11
12
// ํฌ์ธํฐ: ๋งค๋ฒ ๋ค๋ฆ
int* a = new int(1); // 0x7ffd1c00abc0
int* b = new int(1); // 0x7ffd1c00abe0 โ ๊ฐ์ ๊ฐ 1 ์ธ๋ฐ ์ฃผ์ ๋ค๋ฆ
// ํด์: ํญ์ ๊ฐ์
size_t h1 = std::hash<int>{}(1); // ์: 1
size_t h2 = std::hash<int>{}(1); // ์: 1 โ ๊ฐ์ ํค๋ ํญ์ ๊ฐ์ ํด์
// ๋ค๋ฅธ ํค๊ฐ ๊ฐ์ ํด์์ผ ์๋ ์์ (์ถฉ๋)
size_t h3 = std::hash<std::string>{}("foo");
size_t h4 = std::hash<std::string>{}("xyz");
// h3 == h4 ๊ฐ๋ฅ โ ๊ฐ์ ๋ฒํท์ ๋ค์ด๊ฐ โ ์ถฉ๋
์ด ๊ฒฐ์ ์ฑ์ด ํด์ํ
์ด๋ธ์ ๋ณธ์ง. ๋ง์ฝ hash("Alice") ๊ฐ ํธ์ถ๋ง๋ค ๋ค๋ฅธ ๊ฐ์ด๋ฉด ํ ๋ฒ ๋ฃ์ ๋ค ๋ค์ ์ฐพ์ ์ ์๋ค.
16-4. โ๊ทธ๋๋ ๋ ๋ค ์ ์ ์๋๋โ
๋ง๋ค. ๊ทธ๋์ ๊ณตํต์ ์ด ์๊ธด ํ๋ค:
- ๋ ๋ค ๋ณดํต 64๋นํธ ์ ์ (
size_t,uintptr_t) - ๋ ๋ค ์ด๋ค ์์น๋ฅผ ์๋ณํ๋ ๋ฐ ์ฐ์ (ํฌ์ธํฐ = ๋ฉ๋ชจ๋ฆฌ ์์น, ํด์ = ๋ฒํท ์์น)
- ๋ ๋ค โraw value ๋ง ๋ณด๋ฉด ์๋ฏธ ์๋ ์ซ์โ
ํ์ง๋ง ์์น์ ์ ์๊ฐ ๋ค๋ฅด๋ค:
1
2
ํฌ์ธํฐ: RAM ์ ์ ๋ ์ฃผ์ โ OS ๊ฐ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ๋งคํ์ ํด ์ค์ผ ์ง์ง ๋ฐ์ดํฐ์ ๋ฟ์
ํด์: ๋ฒํท ๋ฐฐ์ด์ ์๋ ์ธ๋ฑ์ค โ ๋ชจ๋๋ก ์ฐ์ฐ์ ํ ๋ค์์ผ ์๋ฏธ๊ฐ ์๊น
16-5. ํท๊ฐ๋ฆฌ์ง ์๋ ๋น์
1
2
3
4
5
6
7
8
ํฌ์ธํฐ = ์ง ์ฃผ์
"์์ธ์ ๊ฐ๋จ๊ตฌ ํ
ํค๋๋ก 123๋ฒ์ง" โ ๊ทธ ์์น์ ๊ฐ๋ฉด ์ง์ง ์ง(๋ฐ์ดํฐ) ์ด ์๋ค.
์ฃผ์ ์์ฒด๋ก ๋ฐ์ดํฐ๋ฅผ ์ฐพ์๊ฐ ์ ์๋ค.
ํด์ = ์ฌ๋ฌผํจ ๋ฒํธ ๋ฝ๊ธฐ
์ฌ๋ฌผํจ 1000๊ฐ์ง๋ฆฌ ๋ณด๊ด์์์ "์ด๋ฆ์ ์์ ํฉ % 1000" ์ผ๋ก ๋ฒํธ ๊ฒฐ์ .
๊ฐ์ ์ด๋ฆ์ ํญ์ ๊ฐ์ ๋ฒํธ. ๋ค๋ฅธ ์ด๋ฆ์ด ๊ฐ์ ๋ฒํธ์ผ ์๋ ์์ (์ถฉ๋).
๋ฒํธ๋ง ์์๋ ์ฌ๋ฌผํจ์ด ์ด๋ ์๋์ง(๋ฉ๋ชจ๋ฆฌ ์ฃผ์) ๋ ๋ชจ๋ฆ.
16-6. ๊ทธ๋ผ ๋์ด ๋ง๋๋ ์ง์ ์?
ํด์ํ ์ด๋ธ ๋ด๋ถ์์ ํด์ โ ์ธ๋ฑ์ค โ ์ฌ๋กฏ ์ฃผ์ ํ๋ฆ์ ๊ฒฐ๊ตญ ํฌ์ธํฐ๋ก ๋๋๋ค:
1
2
3
4
5
6
7
8
9
10
11
12
13
ํค "Alice"
โ
โผ hash()
4283950122 โ ํด์๊ฐ (์ ์, ๊ฒฐ์ ์ )
โ
โผ % 16
11 โ ๋ฒํท ์ธ๋ฑ์ค
โ
โผ &buckets[11]
0x7ffd1c00abc8 โ ์ฌ๋กฏ์ ์ฃผ์ (ํฌ์ธํฐ)
โ
โผ *
{"Alice", 30} โ ์ค์ ๋ฐ์ดํฐ
ํด์๋ ์ธ๋ฑ์ค ์ฌ๋ฃ ๊น์ง๋ง, ๊ฑฐ๊ธฐ์๋ถํฐ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์(ํฌ์ธํฐ) ๋ก ๋ณํ๋๋ ๊ฒ์ ๋ฐฐ์ด ์ฒจ์ ์ฐ์ฐ(buckets + 11 * sizeof(slot)) ์ ์ผ์ด๋ค.
16-7. ์ ์ ๋ ํ ์ค ์ ์
ํด์๋ โ๊ฐ์ ์ ๋ ฅ โ ๊ฐ์ ์ถ๋ ฅโ ์ ์๊ณ , ํฌ์ธํฐ๋ โํ ๋น์๊ฐ ์ก์ ์ค ๋ฉ๋ชจ๋ฆฌ ์ฃผ์โ ๋ค. ๋ ๋ค ์ ์๋ผ๋ ์ ๋ง ๊ฐ๊ณ ์ถ์ฒยท๊ฒฐ์ ์ฑยท์ญ์ฐธ์กฐ ๊ฐ๋ฅ์ฑ์ด ๋ชจ๋ ๋ค๋ฅด๋ค. ํฌ์ธํฐ๋ ๊ฐ๋ฆฌํค์ง๋ง, ํด์๋ ์ธ๋ฑ์ฑํ๋ค.
ยง15 (ํด์๋ ํ ๋น๊ณผ ๋ฌด๊ด) + ยง16 (ํด์ โ ํฌ์ธํฐ) โ ๋ ์ง๋ฌธ ๋ชจ๋ ํต์ฌ์ โํด์๋ ์์น ์ธ๋ฑ์ค๋ฅผ ์ํ ๊ฒฐ์ ์ ์ ์โ ๋ผ๋ ์ ์ ํ ์ค๋ก ์๋ ดํ๋ค.
ํ๊ท ๋ค๋ฆฌ
14_std_map.mdโ ๋ณธ ๋ฌธ์์ ์๋ณธ. ๋ต๋ณ ๊ทผ๊ฑฐ๊ฐ ๋ชจ๋ ์ฌ๊ธฐ์ ์์.13_vector_vs_list.mdโ ๋ ธ๋ ์์ ์ฑยท์บ์ ์นํ์ฑ ํ๋ ์. ยง9 ๊ฒ์ ์์ง ์ฒ ํ๊ณผ ์ง๊ฒฐ.11_smart_pointer.mdโtry_emplace+unique_ptr์์ ํจํด + ํ ์๋ช ์๋ํ.03_new_vs_malloc.mdโ ํ ๋ฉ๋ชจ๋ฆฌ ์์ญ (ยง7-1, ยง14 ์ ์ง๊ฒฐ).10_pointer_deepdive.mdโ rehash ํ ๋๊ธ๋ง ํฌ์ธํฐ (ยง12-2 iterator ๋ฌดํจํ์ ๊ฐ์ ๋งฅ๋ฝ).