CS โ vector vs list
๐ 04/28 โ std::vector vs std::list ๋ชจ์๋ฉด์ ์ค๋น
๋ด์ผ(04/29) ๋ชจ์๋ฉด์ ์ฃผ์ : โ
std::vector์std::list์ ์ฐจ์ด์ ์ ๋ฌด์์ธ๊ฐ์? ์ธ์ ์ด๋ค ๊ฑธ ์ฐ๋์?โ ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์ โ ์๊ฐ ๋ณต์ก๋ ํจ์ โ CPU ์บ์(โ ํต์ฌ) โ iterator ๋ฌดํจํ/์์ธ ์์ ์ฑ โ ์ธ์ list๋ฅผ ์จ์ผ ํ๋ โ TArray/UE ์ปจํ ์ด๋ ๊ผฌ๋ฆฌ์ง๋ฌธ ์ฐ๊ฒฐ ๋ค๋ฆฌ
ํ์ต ์์ญ ์ ํ์ โ ์ธ์ด ๋ฌธ๋ฒ์์ STL + ์์คํ ์ผ๋ก
์ง๊ธ๊น์ง์ ํ๋ฆ์ ์ ๊น ์ ๋ฆฌํฉ๋๋ค.
1
2
3
4
5
6
05~10๋ฒ vtable / virtual ์๋ฉธ์ / ํฌ์ธํฐ / ๋๊ธ๋ง โ C++ ์ธ์ด ์๋ฏธ๋ก (๋คํ์ฑยท๋ฉ๋ชจ๋ฆฌ)
11๋ฒ ์ค๋งํธ ํฌ์ธํฐ (unique/shared/weak) โ RAII ๊ธฐ๋ฐ ์์ ๊ด๋ฆฌ
12๋ฒ ๊ฐ์ฒด ๋ณต์ฌ ๊ธ์ง / Rule of N / move-only โ C++ ์ธ์ด ๋ฌธ๋ฒ (ํน๋ณ ๋ฉค๋ฒ ํจ์)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
13๋ฒ std::vector vs std::list โ STL ์ปจํ
์ด๋ + ์์คํ
(CPU ์บ์) โ
์ดํ ํด์๋งต / ์ ๋ ฌ / ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ / ์ค๋ ๋ ๋ชจ๋ธ ๋ฑ โ STL ยท OS ยท HW ์์ญ
12๋ฒ๊น์ง๊ฐ โ์ด ์ฝ๋๊ฐ ์ด๋ป๊ฒ ์ปดํ์ผ๋๊ณ ์ด๋ค ์๋ฏธ์ธ๊ฐโ ์๋ค๋ฉด, 13๋ฒ๋ถํฐ๋ โ์ด ์๋ฃ๊ตฌ์กฐ๊ฐ ์ค์ ํ๋์จ์ด์์ ์ด๋ป๊ฒ ๋์ํ๊ณ ์ ๋น ๋ฅธ/๋๋ฆฐ๊ฐโ ๋ก ์ง๋ฌธ ์ถ์ด ๋ฐ๋๋๋ค.
ํนํ ์ด ์ฃผ์ ์ ํต์ฌ์ โ์ด๋ก ์๊ฐ ๋ณต์ก๋๊ฐ ๊ฐ์๋ ์บ์ ์นํ์ฑ์ด ์ค์ ์ฑ๋ฅ์ ๊ฒฐ์ ํ๋คโ ์
๋๋ค. O(1) < O(n)์ด๋ผ๋ ๊ต๊ณผ์ ๋ต์ด ํ๋ CPU์์ ์ ๋ฐ๋๋ก ๋ค์งํ๋ ๊ฐ์ฅ ์ ๋ช
ํ ์ฌ๋ก๊ฐ ๋ฐ๋ก vector vs list์
๋๋ค.
๋ชจ์๋ฉด์ ๋ต๋ณ
std::vector์ std::list๋ ๋ชจ๋ ์ํ์ค ์ปจํ
์ด๋์ด์ง๋ง ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์์ด ์ ๋ฐ๋์
๋๋ค. vector๋ ์ฐ์ ๋ฉ๋ชจ๋ฆฌ(contiguous) ๋์ ๋ฐฐ์ด๋ก, capacity๊ฐ ๋ถ์กฑํ๋ฉด ๋ณดํต 1.5~2๋ฐฐ๋ก ์ฌํ ๋นํ๋ฉด์ ๋ชจ๋ ์์๋ฅผ ์ ๋ฒํผ๋ก ์ฎ๊น๋๋ค. list๋ ์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ก ๊ฐ ๋
ธ๋๊ฐ ํ์ ๋ฐ๋ก ํ ๋น๋๊ณ prev/next ํฌ์ธํฐ๋ก ์ฐ๊ฒฐ๋ฉ๋๋ค.
์ด๋ก ์๊ฐ ๋ณต์ก๋๋ง ๋ณด๋ฉด list๊ฐ ์ ๋ฆฌํ ๋ฏ ๋ณด์
๋๋ค. ์ค๊ฐ ์ฝ์
์ด vector๋ O(n), list๋ O(1)์ด๋๊น์. ํ์ง๋ง ์ค์ธก ์ฑ๋ฅ์ ๊ฑฐ์ ํญ์ vector๊ฐ ์์นํฉ๋๋ค. ์ด์ ๋ CPU ์บ์ ๋๋ฌธ์
๋๋ค. CPU๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ 64๋ฐ์ดํธ ์บ์ ๋ผ์ธ ๋จ์๋ก ๊ฐ์ ธ์ค๊ณ , ํ ๋ฒ ๊ฐ์ ธ์จ ๋ผ์ธ ์์ ๋ฐ์ดํฐ๋ L1 ๊ธฐ์ค 1ns ์ ๋๋ก 100๋ฐฐ ๋น ๋ฅด๊ฒ ์ ๊ทผ๋ฉ๋๋ค. vector๋ ์์๊ฐ ์ฐ์์ด๋ผ ํ ์บ์ ๋ผ์ธ์ ์ฌ๋ฌ ๊ฐ๊ฐ ๋์์ ๋ค์ด์ค๊ณ ํ๋์จ์ด ํ๋ฆฌํ์ฒ๊ฐ ๋ค์ ๋ผ์ธ์ ๋ฏธ๋ฆฌ ๋ก๋ํฉ๋๋ค. list๋ ๋
ธ๋๊ฐ ํ ์ฌ๊ธฐ์ ๊ธฐ ํฉ์ด์ ธ ์์ด ๋งค ๋
ธ๋ ์ ๊ทผ๋ง๋ค ์บ์ ๋ฏธ์ค๊ฐ ๋๊ณ prefetch๊ฐ ๋์ํ์ง ์์ต๋๋ค. 1M๊ฐ ์ ์ ์ํ ๋ฒค์น๋งํฌ์์ vector๋ ์ฝ 1ms, list๋ ์ฝ 100ms โ ์ด๋ก ์ ๊ฐ์๋ฐ ์ค์ธก์ 100๋ฐฐ ์ฐจ์ด๊ฐ ๋ฉ๋๋ค.
iterator ๋ฌดํจํ ๊ท์น๋ ๋ค๋ฆ ๋๋ค. vector๋ ์ฌํ ๋น์ด ์ผ์ด๋๋ฉด ๋ชจ๋ iterator๊ฐ ๋ฌดํจํ๋๊ณ , ์ค๊ฐ insert/erase๋ ๊ทธ ์์น ์ดํ๊ฐ ๋ฌดํจํ๋ฉ๋๋ค. list๋ ์ญ์ ๋ ๋ ธ๋ ์์ ๋ง ๋ฌดํจํ๋๊ณ ๋๋จธ์ง๋ ์์ ํด์ splice/merge ๊ฐ์ ๋ ธ๋ ์ฌ๋ฐฐ์น ์ฐ์ฐ์ด ๊น๋ํฉ๋๋ค. ์ด๊ฒ list์ ๊ฑฐ์ ์ ์ผํ ์ค์ฉ์ ๊ฐ์ ์ ๋๋ค.
๊ฒฐ๋ก ์ ์ผ๋ก ํ๋ ํ๋์จ์ด์์ list๋ ๊ฑฐ์ ํญ์ ์๋ชป๋ ์ ํ์
๋๋ค. Stroustrup์ด ์ง์ ๊ฐ์ฐ์์ โstd::vector๋ฅผ ์ฐ์ธ์. ์์ฌ์ค๋ฌ์ฐ๋ฉด ๊ทธ๋๋ vector๋ฅผ ์ฐ์ธ์โ๋ผ๊ณ ๊ถ๊ณ ํ๋ ๊ฒ๋ ์ด ์ด์ ์
๋๋ค. list๊ฐ ์ ๋นํ๋๋ ๋๋ฌธ ์ผ์ด์ค๋ ๋งค์ฐ ํฐ ๊ฐ์ฒด + ์ฆ์ ์ค๊ฐ splice + iterator ์์ ์ฑ์ด ์ ๋์ ์ผ๋ก ํ์ํ ๊ฒฝ์ฐ๋ฟ์
๋๋ค. ๋์ ์ ์ถฉ์์ด ํ์ํ๋ฉด ์ฒญํฌ ๊ธฐ๋ฐ์ธ std::deque๋ฅผ ๋ณด๋ ๊ฒ ๋ณดํต ๋ ํฉ๋ฆฌ์ ์
๋๋ค.
์ธ๋ฆฌ์ผ์์๋ ์ด ์ฒ ํ์ด ๋ ๊ฐํ๊ฒ ๋๋ฌ๋ฉ๋๋ค. TArray๊ฐ vector ๋์์ผ๋ก 1๊ธ ์๋ฏผ์ด๊ณ , std::list์ ์ง์ ๋์ํ๋ ์๋ฃ๊ตฌ์กฐ๋ ์๋์ ์ผ๋ก 1๊ธ์ผ๋ก ๋์ง ์์์ต๋๋ค. TLinkedList/TDoubleLinkedList๋ ์์ง๋ง ๊ฐ๋ฒผ์ด ํฌํผ ์์ค์
๋๋ค. ์บ์ ์นํ์ฑ์ด ๊ฒ์ ์์ง ์ฑ๋ฅ์ ์ง๊ฒฐ๋๊ธฐ ๋๋ฌธ์
๋๋ค.
ํต์ฌ ๊ฐ๋
| ๋ถ๋ฅ | ํค์๋ | ํ ์ค ์ ์ |
|---|---|---|
| ์ปจํ ์ด๋ ๊ธฐ๋ณธ | std::vector | ์ฐ์ ๋ฉ๋ชจ๋ฆฌ ๋์ ๋ฐฐ์ด. ๋ push_back amortized O(1) |
| ย | std::list | ์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ. ๋ ธ๋๊ฐ ํ์ ๋ถ์ฐ, prev/next ํฌ์ธํฐ |
| ย | std::forward_list | ๋จ๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ. ๋ ธ๋๋น 8๋ฐ์ดํธ ์ ์ฝ |
| ย | std::deque | ์ฒญํฌ ๊ธฐ๋ฐ ๋๋ธ์๋ ํ. push_front/back ๋ชจ๋ O(1) |
| ย | std::array | ๊ณ ์ ํฌ๊ธฐ ๋ฐฐ์ด. ์ปดํ์ผ ํ์ size, ์คํ ํ ๋น ๊ฐ๋ฅ |
| ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์ | ์ฐ์ ๋ฉ๋ชจ๋ฆฌ (Contiguous) | ์์๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ์ธ์ . vectorยทarray์ ํต์ฌ ํน์ฑ |
| ย | ๋ถ์ฐ ํ ๋น (Scattered) | ๋ ธ๋๋ง๋ค ๋ณ๋ ํ ํ ๋น. list์ ํต์ฌ ํน์ฑ |
| ย | capacity vs size | size: ์ค์ ์์ ์, capacity: ํ ๋น๋ ์ฌ๋กฏ ์ |
| ย | ์ฌํ ๋น (Reallocation) | size > capacity ์ ์ ๋ฒํผ ํ ๋น + ๊ธฐ์กด ์์ ์ด์ |
| ย | ์ฑ์ฅ ์ธ์ (Growth Factor) | ๋ณดํต 1.5x(MSVC) ~ 2x(libstdc++) โ amortized O(1) ๋ณด์ฅ |
| ์๊ฐ ๋ณต์ก๋ | amortized O(1) | ํ๊ท ์ ์ผ๋ก O(1)์ด์ง๋ง ๊ฐ๋ O(n) ๋น์ฉ. ๋ถํ ์ํ ๋ถ์ |
| ย | ์์ ์ ๊ทผ (Random Access) | v[i]๋ก ์ฆ์ i๋ฒ์งธ ์์. vector O(1), list O(n) |
| ย | ์์ฐจ ์ ๊ทผ (Sequential Access) | iterator++๋ก ์ํ โ list๋ O(n)์ด์ง๋ง ์บ์ ๋ฏธ์ค๋ก ์ค์ธก ๋๋ฆผ |
| CPU ์บ์ โ | ๋ฉ๋ชจ๋ฆฌ ๊ณ์ธต (Memory Hierarchy) | ๋ ์ง์คํฐ โ L1 โ L2 โ L3 โ DRAM (์๋ ๊ฒฉ์ฐจ 100๋ฐฐ) |
| ย | L1 ์บ์ | ~32KB, ~1ns ์ ๊ทผ. ์ฝ์ด๋น ์ ์ฉ |
| ย | L2 ์บ์ | ~256KB, ~3ns ์ ๊ทผ. ์ฝ์ด๋น ์ ์ฉ(๋ณดํต) |
| ย | L3 ์บ์ | ~8MB, ~12ns ์ ๊ทผ. ์ฝ์ด ๊ฐ ๊ณต์ |
| ย | DRAM | GB ๋จ์, ~100ns ์ ๊ทผ. L1 ๋๋น 100๋ฐฐ ๋๋ฆผ |
| ย | ์บ์ ๋ผ์ธ (Cache Line) | ๋ฉ๋ชจ๋ฆฌ ์ ์ก ๋จ์. ๋ณดํต 64๋ฐ์ดํธ (x86_64) |
| ย | ๊ณต๊ฐ ์ง์ญ์ฑ (Spatial Locality) | ๊ฐ๊น์ด ์ฃผ์์ ๋ฐ์ดํฐ๊ฐ ๊ณง ์ฌ์ฉ๋ ํ๋ฅ ์ด ๋์ |
| ย | ์๊ฐ ์ง์ญ์ฑ (Temporal Locality) | ํ ๋ฒ ์ด ๋ฐ์ดํฐ๋ฅผ ๊ณง ๋ค์ ์ธ ํ๋ฅ ์ด ๋์ |
| ย | ํ๋์จ์ด ํ๋ฆฌํ์ฒ (Prefetcher) | ์์ฐจ ์ ๊ทผ ํจํด ๊ฐ์ง โ ๋ค์ ์บ์ ๋ผ์ธ ์๋ ๋ก๋ |
| ย | ์บ์ ๋ฏธ์ค (Cache Miss) | L1/L2/L3์ ์์ด์ ๋ ๋๋ฆฐ ๊ณ์ธต๊น์ง ๋ด๋ ค๊ฐ์ผ ํ๋ ์ํฉ |
| ย | ์บ์ ์นํ์ฑ (Cache Friendliness) | ์๊ณ ๋ฆฌ์ฆ์ด ์บ์ ๋์์ ์ ๋ง๋ ์ ๋. ์ค์ธก ์ฑ๋ฅ ๊ฒฐ์ |
| iterator ๋ฌดํจํ | ์ฌํ ๋น ๋ฌดํจํ | vector capacity ์ฆ๊ฐ ์ ๋ชจ๋ iterator/ํฌ์ธํฐ/์ฐธ์กฐ ๋ฌดํจํ |
| ย | ๋ถ๋ถ ๋ฌดํจํ | vector insert/erase ์ ํด๋น ์์น ์ดํ๋ง ๋ฌดํจํ |
| ย | ๋ ธ๋ ์์ ์ฑ (Node Stability) | list/map์ ์ญ์ ๋ ๋ ธ๋๋ง ๋ฌดํจํ โ splice/merge ์์ |
| ๋ฉ๋ชจ๋ฆฌ ํจ์จ | ๋ ธ๋ ์ค๋ฒํค๋ | list ๋ ธ๋ = ๋ฐ์ดํฐ + prev 8B + next 8B + ํ ํค๋ |
| ย | ํ ๋น์ ํธ์ถ ํ์ | vector๋ 1ํ, list๋ Nํ(๋ ธ๋๋ง๋ค) |
| ย | ๋ฉ๋ชจ๋ฆฌ ๋จํธํ (Fragmentation) | list๋ ์์ ๋ธ๋ก์ ์์ฃผ ํ ๋น โ ๋จํธํ ์ ๋ฐ |
| ๊ถ์ฅ ๋ฃฐ | โVector firstโ ๋ฃฐ | StroustrupยทSutter โ ์์ฌ์ค๋ฌ์ฐ๋ฉด vector |
| ย | TArray (Unreal) | ์ธ๋ฆฌ์ผํ vector. UPROPERTYยทGCยท๋ฆฌํ๋ ์ ํตํฉ |
| ย | TLinkedList / TDoubleLinkedList | ์ธ๋ฆฌ์ผ ์ฐ๊ฒฐ ๋ฆฌ์คํธ. 1๊ธ์ด ์๋ ํฌํผ ์์ค |
๋ชฉ์ฐจ
- ํต์ฌ ์์ฝ ์นด๋
- ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์ ์ฐจ์ด
- ์๊ฐ ๋ณต์ก๋ ํจ์ โ ์ด๋ก vs ์ค์ธก
- CPU ์บ์ โ ์ค์ ์ฑ๋ฅ์ ๊ฒฐ์ ํ๋ ์์ญ โ
- iterator ๋ฌดํจํ / ์์ธ ์์ ์ฑ / ๋ฉ๋ชจ๋ฆฌ ํจ์จ
- ์ธ์ list๋ฅผ ์จ์ผ ํ๋ โ ์ฌ์ค์ ๊ฑฐ์ ์์
- ์ธ๋ฆฌ์ผ
TArrayvs STL - ํ๊ท ๋ค๋ฆฌ โ ๋ค๋ฅธ CS ํ์ผ ์ฐ๊ฒฐ
- ๊ผฌ๋ฆฌ์ง๋ฌธ ์์ ๊ฒฝ๋ก
- ๋ชจ์๋ฉด์ ๋ต๋ณ ํ ํ๋ฆฟ (1๋ถ / 3๋ถ)
1. ํต์ฌ ์์ฝ ์นด๋
ํ ์ค ์์ฝ 30์ด
1
2
3
4
vector โ ์ฐ์ ๋ฉ๋ชจ๋ฆฌ. ์บ์ ์นํ. ์์ ์ ๊ทผ O(1). ๋ push amortized O(1).
list โ ๋
ธ๋ ๋ถ์ฐ ํ. ์บ์ ์ ๋. ์์ ์ ๊ทผ O(n). ์ค๊ฐ ์ฝ์
์ด๋ก ์ O(1).
์ค์ธก โ ๊ฑฐ์ ๋ชจ๋ ์ํฌ๋ก๋์์ vector ์์น (100๋ฐฐ ์ฐจ์ด๋ ํํจ).
๋ฃฐ โ "์์ฌ์ค๋ฌ์ฐ๋ฉด vector. ๊ทธ๋๋ ์์ฌ์ค๋ฌ์ฐ๋ฉด ๊ทธ๋๋ vector."
์๊ฐ ๋ณต์ก๋ ํ 30์ด
| ์ฐ์ฐ | vector | list | ์ค์ธก ์ฐ์ |
|---|---|---|---|
์์ ์ ๊ทผ v[i] | O(1) | O(n) | vector |
| ๋ ์ฝ์ push_back | amortized O(1) | O(1) | vector (์บ์) |
| ๋ ์ญ์ pop_back | O(1) | O(1) | vector |
| ์ ์ฝ์ push_front | O(n) | O(1) | list (ํฐ N์์) |
| ์ค๊ฐ ์ฝ์ (์์น ์ ๋) | O(n) | O(1) | ๊ฑฐ์ vector โ |
| ์ค๊ฐ ์ญ์ (์์น ์ ๋) | O(n) | O(1) | ๊ฑฐ์ vector โ |
| ๊ฒ์ find | O(n) | O(n) | vector (์บ์) |
| ์์ฐจ ์ํ | O(n) | O(n) | vector ~100๋ฐฐ ๋น ๋ฆ |
โ ํ์ ํญ๋ชฉ์ด ๋ฉด์ ๋จ๊ณจ ํจ์ โ โlist๊ฐ O(1)์ธ๋ฐ ์ vector๊ฐ ๋น ๋ฅธ๊ฐโ
CPU ์บ์ 30์ด
1
2
3
4
5
6
7
8
9
10
11
๋ฉ๋ชจ๋ฆฌ ๊ณ์ธต (์๋ ๊ฒฉ์ฐจ):
L1 (~1ns, 32KB) L2 (~3ns, 256KB) L3 (~12ns, 8MB) DRAM (~100ns)
โ 100๋ฐฐ ๋๋ฆผ
์บ์ ๋ผ์ธ = 64๋ฐ์ดํธ โ CPU๊ฐ ํ ๋ฒ์ ๊ฐ์ ธ์ค๋ ๋จ์
๊ณต๊ฐ ์ง์ญ์ฑ : ๊ฐ์ ๋ผ์ธ์ ๋ค๋ฅธ ๋ฐ์ดํฐ๋ ๊ฑฐ์ ๊ณต์ง
์๊ฐ ์ง์ญ์ฑ : ์ต๊ทผ ์ด ๋ฐ์ดํฐ๋ ์บ์์ ๋จ์์์
ํ๋ฆฌํ์ฒ : ์์ฐจ ํจํด ๊ฐ์ง โ ๋ค์ ๋ผ์ธ ๋ฏธ๋ฆฌ ๋ก๋
vector: ์ฐ์ โ ํ ๋ผ์ธ์ 16๊ฐ int โ ์บ์ ํํธ์จ โ โ prefetch ์๋
list: ๋ถ์ฐ โ ๋
ธ๋๋ง๋ค ์บ์ ๋ฏธ์ค โ DRAM 100ns ์๋ณต N๋ฒ โ 100๋ฐฐ ๋๋ฆผ
๊ผฌ๋ฆฌ์ง๋ฌธ ์ฐ๊ฒฐ ๋งต
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
std::vector vs std::list
โโโ ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์
โ โโโ ์ฐ์ ๋ฉ๋ชจ๋ฆฌ vs ๋ถ์ฐ ๋
ธ๋
โ โโโ capacity / ์ฑ์ฅ ์ธ์ (1.5x ~ 2x)
โโโ ์๊ฐ ๋ณต์ก๋ ํจ์
โ โโโ list O(1) ์ฝ์
์ ์ค์ฒด โ "์์น iterator๋ฅผ ์ด๋ฏธ ๋ค๊ณ ์์ ๋"
โ โโโ ๊ฒ์์ด ํ์ํ๋ฉด ๊ฒฐ๊ตญ O(n) โ vector๊ฐ ์บ์๋ก ์์น
โโโ CPU ์บ์ โ
(โ
ํต์ฌ ์์ญ)
โ โโโ ๋ฉ๋ชจ๋ฆฌ ๊ณ์ธต / ์บ์ ๋ผ์ธ 64B
โ โโโ ๊ณต๊ฐ ์ง์ญ์ฑ / ํ๋ฆฌํ์ฒ
โ โโโ Stroustrup ๊ฐ์ฐ: 1M ์ํ vector ~1ms, list ~100ms
โโโ iterator ๋ฌดํจํ
โ โโโ vector โ ์ฌํ ๋น ์ ์ ์ฒด / insertยทerase ์ ๋ถ๋ถ
โ โโโ list โ ์ญ์ ๋
ธ๋ ์์ ๋ง (splice/merge ์์ )
โโโ ์์ธ ์์ ์ฑ
โ โโโ vector โ strong guarantee ์ด๋ ค์ (move ์ noexcept ํ์)
โ โโโ list โ push_back/push_front strong guarantee
โโโ ์ธ์ list?
โ โโโ ๋งค์ฐ ํฐ ๊ฐ์ฒด + ์ฆ์ splice + iterator ์์ ์ฑ ํ์
โ โโโ ๊ทธ ์ธ์ ๊ฑฐ์ ํญ์ vector / deque
โโโ ์ธ๋ฆฌ์ผ TArray
โโโ vector ๋์ 1๊ธ ์๋ฏผ
โโโ ํ์ค list ๋์ ์๋์ ์ผ๋ก ๋์ง ์์
โโโ TLinkedList๋ ํฌํผ ์์ค
2. ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์ ์ฐจ์ด
ํต์ฌ ํ ๋ฌธ์ฅ
vector๋ ์ฐ์ ๋ฉ๋ชจ๋ฆฌ์ ์์๋ฅผ ํ ์ค๋ก ๋ฐฐ์นํ๊ณ ,list๋ ๊ฐ ๋ ธ๋๋ฅผ ํ ์ฌ๊ธฐ์ ๊ธฐ ๋ฐ๋ก ํ ๋นํด ํฌ์ธํฐ๋ก ์ฐ๊ฒฐํฉ๋๋ค. ์ด ํ ๊ฐ์ง ์ฐจ์ด๊ฐ ๋ชจ๋ ์ฑ๋ฅ ํน์ฑ์ ๊ฒฐ์ ํฉ๋๋ค.
2-1. vector โ ์ฐ์ ๋ฉ๋ชจ๋ฆฌ
1
2
3
4
5
6
std::vector<int> v;
v.reserve(8);
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
1
2
3
4
5
6
7
8
9
10
11
ํ์ ํ ๋ฉ์ด๋ฆฌ๋ก ํ ๋น๋ ๋ฒํผ:
[10][20][30][40][ . ][ . ][ . ][ . ]
โ โ
begin() capacity ๋ (size=4, capacity=8)
vector ๊ฐ์ฒด ์์ฒด๋ ๋ณดํต 3๊ฐ ํฌ์ธํฐ(24๋ฐ์ดํธ, x86_64):
โโโโโโโโโโโโโโฌโโโโโโโโโโโโโฌโโโโโโโโโโโโโ
โ data ptr โ size โ capacity โ
โโโโโโโฌโโโโโโโดโโโโโโโโโโโโโดโโโโโโโโโโโโโ
โโโโ ์ ์ฐ์ ๋ฒํผ์ ์ฒซ ์์
ํน์ง:
&v[0],&v[1],&v[2]โฆ ๊ฐ ์ฐ์๋ ์ฃผ์- ํ ๋ฒ์
operator new๋ก ์ ์ฒด ๋ฒํผ ํ ๋น โ ํ ๋น์ ํธ์ถ 1ํ v.data()๋ก raw pointer๋ฅผ ์ป์ด C API์ ๊ทธ๋๋ก ๋๊ธธ ์ ์์- ์บ์ ๋ผ์ธ 64B ์์
int(4B) 16๊ฐ๊ฐ ๋ค์ด์ด
2-2. list โ ๋ถ์ฐ๋ ๋ ธ๋
1
std::list<int> l = {10, 20, 30, 40};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
๊ฐ ๋
ธ๋๊ฐ ํ์ ๋ค๋ฅธ ์์น์ ๋ฐ๋ก ํ ๋น๋จ:
์ฃผ์ 0x1000: ์ฃผ์ 0x4F80: ์ฃผ์ 0x9210:
โโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโ โโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโ โโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโ
โ prev โ next โ data โ โ prev โ next โ data โ โ prev โ next โ data โ
โ nullptrโ 0x4F80 โ 10 โ โ 0x1000 โ 0x9210 โ 20 โ โ 0x4F80 โ 0xCC30 โ 30 โ
โโโโโโโโโโดโโโโโโโโโดโโโโโโโโโ โโโโโโโโโโดโโโโโโโโโดโโโโโโโโโ โโโโโโโโโโดโโโโโโโโโดโโโโโโโโโ
list ๊ฐ์ฒด ์์ฒด:
โโโโโโโโโโโโฌโโโโโโโโโโโฌโโโโโโโโโโโ
โ head โ tail โ size โ
โโโโโโฌโโโโโโดโโโโโโโโโโโดโโโโโโโโโโโ
โโโโ ์ฒซ ๋
ธ๋ (0x1000)
๊ฐ ๋
ธ๋ ํฌ๊ธฐ (int ๋ฐ์ดํฐ ๊ธฐ์ค):
prev 8B + next 8B + data 4B + ํจ๋ฉ 4B + ํ ํ ๋น ํค๋ ~16B
= 40๋ฐ์ดํธ (์ค์ ๋ฐ์ดํฐ 4B๋ฅผ ์ํด 36B ์ค๋ฒํค๋ โ
)
ํน์ง:
- ๋
ธ๋๋ง๋ค ๊ฐ๋ณ
operator newํธ์ถ โ 1M๊ฐ list = 100๋ง ํ ํ ๋น - ๋
ธ๋ ์ฃผ์๊ฐ ๋ฌด์์ โ
next๋ก ๋ฐ๋ผ๊ฐ์ผ๋ง ๋ค์์ ์ฐพ์ - ๋ฐ์ดํฐ 4๋ฐ์ดํธ๋ฅผ ์ํด 36๋ฐ์ดํธ ์ค๋ฒํค๋ (900% ๋ฉ๋ชจ๋ฆฌ ๋ญ๋น)
- ๋ ธ๋๋ค์ด ์บ์ ๋ผ์ธ ๊ฒฝ๊ณ๋ฅผ ๋๋๋ค์ด ๋งค ๋ ธ๋ ์ ๊ทผ๋ง๋ค ์ ๋ผ์ธ ๋ก๋ ๊ฐ๋ฅ์ฑ
2-3. ์ ๋ ๋น๊ต
int 1,000,000๊ฐ๋ฅผ ๋ด๋๋ค๊ณ ๊ฐ์ (x86_64):
| ํญ๋ชฉ | vector<int> | list<int> |
|---|---|---|
| ๋ฐ์ดํฐ ๋ฉ๋ชจ๋ฆฌ | 4 MB | 4 MB |
| ๋ฉํ ์ค๋ฒํค๋ | 24 B (๊ฐ์ฒด) + capacity ์ฌ๋กฏ ์ผ๋ถ | 40 MB (๋ ธ๋ ํค๋+ํฌ์ธํฐ) |
| ์ด ๋ฉ๋ชจ๋ฆฌ | ~4 MB | ~44 MB |
| ํ ๋น์ ํธ์ถ | 1ํ (์ฌํ ๋น ์ ์ธ) | 1,000,000ํ |
| ์บ์ ๋ผ์ธ ์ ์ (์ํ ์) | ~62,500๊ฐ | ์ต๋ 1,000,000๊ฐ |
list๋ ๋ฐ์ดํฐ์ 10๋ฐฐ ๋ฉ๋ชจ๋ฆฌ, 100๋ง ๋ฐฐ ํ ๋น ํ์๋ฅผ ์ฌ์ฉํฉ๋๋ค.
2-4. capacity์ ์ฑ์ฅ ์ธ์
vector๋ capacity๊ฐ ์ฐจ๋ฉด ๋ ํฐ ๋ฒํผ๋ฅผ ์๋ก ํ ๋นํ๊ณ ๊ธฐ์กด ์์๋ฅผ ์ฎ๊น๋๋ค.
1
2
3
4
5
std::vector<int> v;
for (int i = 0; i < 10; ++i) {
v.push_back(i);
std::cout << "size=" << v.size() << " cap=" << v.capacity() << "\n";
}
1
2
3
4
5
6
7
8
9
10
size=1 cap=1
size=2 cap=2
size=3 cap=4 โ ์ฌํ ๋น, 1โ2โ4
size=4 cap=4
size=5 cap=8 โ ์ฌํ ๋น
size=6 cap=8
size=7 cap=8
size=8 cap=8
size=9 cap=16 โ ์ฌํ ๋น
size=10 cap=16
์ฑ์ฅ ์ธ์:
- libstdc++ (GCC): 2๋ฐฐ ์ฑ์ฅ โ
1, 2, 4, 8, 16, ... - MSVC STL: 1.5๋ฐฐ ์ฑ์ฅ โ
1, 2, 3, 4, 6, 9, 13, 19, 28, ... - 1.5๋ฐฐ๋ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฌ์ฉ์ ์ฝ๊ฐ ์ ๋ฆฌ, 2๋ฐฐ๋ amortized ๋ถ์์ ๋จ์ ์ ๋ฆฌ
amortized O(1)์ด ๋ณด์ฅ๋๋ ์ด์ : N๊ฐ push_back์ ๋์ ๋น์ฉ์ด O(2N) (๋๋ O(3N))์ด๋ผ ํ๊ท ์ด ์์ ์๊ฐ.
1
2
3
4
5
// ๋ฏธ๋ฆฌ reserve๋ก ์ฌํ ๋น ํํผ โ ํฐ ๋ฐ์ดํฐ์ ๋งค์ฐ ํจ๊ณผ์
std::vector<int> v;
v.reserve(1'000'000); // ํ ๋ฒ์ 4MB ํ ๋น
for (int i = 0; i < 1'000'000; ++i)
v.push_back(i); // ์ฌํ ๋น ์์, ๊ฐ์ฅ ๋น ๋ฅธ ํจํด
3. ์๊ฐ ๋ณต์ก๋ ํจ์ โ ์ด๋ก vs ์ค์ธก
ํต์ฌ ํ ๋ฌธ์ฅ
์ด๋ก ์๊ฐ ๋ณต์ก๋๋ ๊ฐ์ง๋ง ์ค์ธก์ 100๋ฐฐ ์ฐจ์ด๊ฐ ํํฉ๋๋ค. โlist๋ ์ค๊ฐ ์ฝ์ ์ด O(1)์ด๋ผ ๋น ๋ฅด๋คโ๋ ๊ฐ์ฅ ์ ๋ช ํ ๋ฉด์ ํจ์ ์ ๋๋ค.
3-1. ํ โ ์ด๋ก ๋ณต์ก๋
| ์ฐ์ฐ | vector | list | ์ค์ ์ฐ์ |
|---|---|---|---|
v[i] ์์ ์ ๊ทผ | O(1) | O(n) | vector โ |
front() / back() | O(1) | O(1) | ๋๋ฅ |
push_back | amortized O(1) | O(1) | vector (์บ์) |
pop_back | O(1) | O(1) | vector |
push_front | O(n) | O(1) | list (ํฐ N์์) |
insert(pos, x) (pos ์๊ณ ์์) | O(n) | O(1) | ๊ฑฐ์ vector โ โ โ |
erase(pos) (pos ์๊ณ ์์) | O(n) | O(1) | ๊ฑฐ์ vector โ โ โ |
find(value) | O(n) | O(n) | vector (์บ์) |
| ์์ฐจ ์ํ | O(n) | O(n) | vector ~100๋ฐฐ โ โ โ |
| ์ ๋ ฌ sort | O(n log n) | O(n log n) | vector (์บ์) |
3-2. ํจ์ 1 โ โlist O(1) ์ฝ์ โ์ ์ค์ฒด
list์ O(1) ์ฝ์ ์ด ์์น iterator๋ฅผ ์ด๋ฏธ ์์ ๋ค๊ณ ์์ ๋๋ง ์ฑ๋ฆฝํ๋ค๋ ์ ์ด ํจ์ ์ ๋๋ค.
1
2
3
4
5
6
7
8
9
10
std::list<int> l = { /* 1,000,000 elements */ };
// ์๋๋ฆฌ์ค A: ์์น iterator๋ฅผ ์ด๋ฏธ ์๊ณ ์์ โ ์ ์งํ๊ฒ O(1)
auto it = SomePreviouslyStoredIterator;
l.insert(it, 999); // โ
์ง์ง O(1)
// ์๋๋ฆฌ์ค B: ๊ฐ์ ์ฐพ์์ ๊ทธ ์์ ์ฝ์
โ find๊ฐ O(n)
auto it = std::find(l.begin(), l.end(), targetValue); // O(n) โ ์บ์ ๋ฏธ์ค ํญํ
l.insert(it, 999); // O(1)์ด์ง๋ง ์์์ ์ด๋ฏธ O(n)์ ์ผ์
// ์ด ๋น์ฉ O(n) + ์บ์ ๋ฏธ์ค Nํ โซ vector์ O(n) ๋ฉ๋ชจ๋ฆฌ ์ด๋
ํ์ค์ ์ธ ์ํฌ๋ก๋๋ ๊ฑฐ์ ์๋๋ฆฌ์ค B์ ๋๋ค. โ๊ฐ X ์์ Y๋ฅผ ์ฝ์ โ ๊ฐ์ ์๊ตฌ์ฌํญ์ด ๋๋ถ๋ถ์ด๋ผ, list์ O(1)์ ๊ฑฐ์ ํ์ฉ๋์ง ์์ต๋๋ค.
3-3. ํจ์ 2 โ vector ์ค๊ฐ ์ฝ์ ์ ์ค์ฒด
vector ์ค๊ฐ ์ฝ์ ์ ์ด๋ก ์ O(n) (๋ค์ชฝ ์์๋ฅผ ํ ์นธ์ฉ ๋ฐ์ด์ผ ํจ)์ด์ง๋ง:
- memmove๊ฐ SIMD ๋ช ๋ น์ด๋ก ํ ๋ฒ์ 16~64๋ฐ์ดํธ์ฉ ์ด๋
- ๋ฐ์ดํฐ๊ฐ ์ด๋ฏธ ์บ์์ ์ฌ๋ผ์ ์์ด ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ด ๊ฑฐ์ ๋ฌด๋ฃ
- ๋ถ๊ธฐ ์์ธก์ด ๊ฑฐ์ ์๋ฒฝ โ ํ์ดํ๋ผ์ธ ์ ๋ถ ์ฌ์ฉ
list ์ค๊ฐ ์ฝ์ ์ ์ด๋ก ์ O(1) (ํฌ์ธํฐ ๋ ๊ฐ๋ง ๊ฐฑ์ )์ด์ง๋ง:
- ์ ๋
ธ๋ ํ ๋น์
operator newํธ์ถ (์์ญ ns ~ ์๋ฐฑ ns) - ํ ๋น์๊ฐ free list ํ์ + lock ๊ฐ๋ฅ
- ์ ๋ ธ๋์ ์์ชฝ ๋ ธ๋์ ์บ์ ๋ฏธ์ค
๊ฒฐ๊ณผ: N์ด ์๋ง~์์ญ๋ง ์ดํ๋ฉด vector๊ฐ ๋ ๋น ๋ฅธ ๊ฒฝ์ฐ๊ฐ ์๋์ ์ผ๋ก ๋ง์.
3-4. ๋ฒค์น๋งํฌ ์ธ์ฌ์ดํธ
Bjarne Stroustrup์ ์ ๋ช ํ ๊ฐ์ฐ (โWhy you should avoid Linked Listsโ, GoingNative 2012):
โ์ ๋ ฌ๋ ์ปจํ ์ด๋์ N๊ฐ ์ ์๋ฅผ ๋ฌด์์ ์์น์ ์ฝ์ ํ๋ค. vector์ list ์ค ์ด๋ ๊ฒ์ด ๋น ๋ฅผ๊น?โ
1
2
3
4
5
6
N | vector | list
โโโโโโโโโโโโโโโโโโโโโโโโโ
500 | 1ms | 1ms โ ๊ฑฐ์ ๋๋ฅ
5000 | 8ms | 35ms โ vector 4๋ฐฐ ๋น ๋ฆ
50000 | 85ms | 1300ms โ vector 15๋ฐฐ ๋น ๋ฆ
500000 | 1100ms | 35000ms โ vector 30๋ฐฐ ๋น ๋ฆ
๊ฒฐ๋ก (์ง์ ์ธ์ฉ): โstd::vector๋ฅผ ์ฐ์ธ์. std::list๋ฅผ ์ฐ์ง ๋ง์ธ์. ์์ฌ์ค๋ฌ์ฐ๋ฉด ๊ทธ๋๋ std::vector๋ฅผ ์ฐ์ธ์.โ
์ด ๊ฒฐ๊ณผ๋ โlist๋ ์บ์ ๋ฏธ์ค 100ns ร ๋ ธ๋ ์โ ๋ก ์ถ์ ๊ฐ๋ฅ โ ์ธ๋ฑ์ฑยท์ฝ์ ์ ์๊ณ ๋ฆฌ์ฆ ๋น์ฉ๋ณด๋ค ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ๋น์ฉ์ด ํจ์ฌ ํฝ๋๋ค.
3-5. ๊ทธ๋ผ list๊ฐ ์ ๋ง ๋น ๋ฅธ ๊ฒฝ์ฐ๋?
์ ๋ฒค์น๋งํฌ์์ list๊ฐ ์ด๊ธด ์ผ์ด์ค๋ ๊ฑฐ์ ์์์ง๋ง, ์ด๋ก ์ ์ผ๋ก๋:
1
2
3
4
5
6
// ๋งค์ฐ ํฐ ๊ฐ์ฒด + ์ฆ์ ์ค๊ฐ splice
struct HugeNode { char payload[4096]; /* 4KB */ };
std::list<HugeNode> a, b;
// ...
a.splice(a.begin(), b); // O(1) โ ๋
ธ๋ ํฌ์ธํฐ๋ง ์ฎ๊น. vector๋ 4KB ร N ๋ณต์ฌ
์ด ๊ฒฝ์ฐ vector๋ ๋ฉ๋ชจ๋ฆฌ ์ด๋ ๋น์ฉ์ด ์ง์ง๋ก ์ปค์ง๋ฏ๋ก list๊ฐ ์ ๋ฆฌ. ๋จ ์ด๋ฐ ์ํฌ๋ก๋๋ ํ์น ์์ต๋๋ค (๋ณดํต vector<unique_ptr<HugeNode>>๋ก ์ฐํ).
4. CPU ์บ์ โ ์ค์ ์ฑ๋ฅ์ ๊ฒฐ์ ํ๋ ์์ญ โ
ํต์ฌ ํ ๋ฌธ์ฅ
ํ๋ CPU๋ ๋ฉ๋ชจ๋ฆฌ๋ณด๋ค 100๋ฐฐ ๋น ๋ฅด๊ณ , ๊ทธ ๊ฒฉ์ฐจ๋ฅผ ์บ์๋ก ๋ฉ์๋๋ค. ์๊ณ ๋ฆฌ์ฆ ์๊ฐ ๋ณต์ก๋๊ฐ ์๋๋ผ ์บ์ ์นํ์ฑ์ด ์ค์ ์ฑ๋ฅ์ ๊ฒฐ์ ํ๋ฉฐ, ์ด๊ฒ vector๊ฐ list๋ฅผ ์๋ํ๋ ๊ทผ๋ณธ ์ด์ ์ ๋๋ค.
4-1. ๋ฉ๋ชจ๋ฆฌ ๊ณ์ธต (Memory Hierarchy)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
์๋ ๊ฒฉ์ฐจ
(๋๋ต)
โโโโโโโโโโโโโโโโโโโ โ CPU ์ฝ์ด
โ ๋ ์ง์คํฐ โ ~32๊ฐ ร 64bit, ~0ns โ
๊ฐ์ฅ ๋น ๋ฆ
โโโโโโโโโโโโโโโโโโโค
โ L1 ์บ์ โ ~32 KB, ~1 ns โโโโ ๋ฐ์ดํฐ/๋ช
๋ น์ด ๋ถ๋ฆฌ
โโโโโโโโโโโโโโโโโโโค ์ฝ์ด๋น ์ ์ฉ
โ L2 ์บ์ โ ~256 KB, ~3 ns
โโโโโโโโโโโโโโโโโโโค ๋ณดํต ์ฝ์ด๋น ์ ์ฉ
โ L3 ์บ์ โ ~8 MB, ~12 ns โโโโ ์ฝ์ด ๊ฐ ๊ณต์
โโโโโโโโโโโโโโโโโโโค
โ DRAM (๋ฉ์ธ) โ ~16 GB, ~100 ns โ
L1 ๋๋น 100๋ฐฐ ๋๋ฆผ
โโโโโโโโโโโโโโโโโโโค
โ SSD โ ~1 TB, ~100,000 ns (์บ์ ์์ญ๊ณผ๋ ๋ณ๊ฐ)
โโโโโโโโโโโโโโโโโโโ
ํต์ฌ ํจ์:
- L1 1ns vs DRAM 100ns โ ์บ์ ๋ฏธ์ค ํ ๋ฒ์ด ์ฝ 100 ์ฌ์ดํด ๋ญ๋น
- ํ๋ CPU๋ ์ฌ์ดํด๋น 4 ๋ช ๋ น์ด ์คํ ๊ฐ๋ฅ โ ์บ์ ๋ฏธ์ค 1ํ = ๋ช ๋ น์ด 400๊ฐ ๋ถ๋์ ์๊ฐ ๋ญ๋น
- ๋ฐ๋ผ์ โ์ฝ๋๋ฅผ ๋น ๋ฅด๊ฒ ํ๋ ค๋ฉด ๋ช ๋ น์ด ๊ฐ์๋ณด๋ค ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด์ ์ค์ฌ๋ผโ
4-2. ์บ์ ๋ผ์ธ (Cache Line)
CPU๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋ฐ์ดํธ์ฉ ๊ฐ์ ธ์ค์ง ์๊ณ ๋ผ์ธ ๋จ์๋ก ๊ฐ์ ธ์ต๋๋ค. x86_64์์ ๋ผ์ธ์ 64๋ฐ์ดํธ.
1
2
3
4
5
6
7
8
9
DRAM์์ L1์ผ๋ก ํ ๋ฒ์ 64๋ฐ์ดํธ ์ ์ก:
์ฃผ์ 0x1000 โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 64๋ฐ์ดํธ = int 16๊ฐ / int64 8๊ฐ / ... โ
์ฃผ์ 0x103F โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ํ ๋ฒ ๊ฐ์ ธ์ค๋ฉด ์ด ์์ ๋ชจ๋ ๋ฐ์ดํฐ๊ฐ ์บ์ ํํธ
โท vector<int>์ 16๊ฐ ์์๊ฐ ํ ๋ผ์ธ์ ๋ค์ด์ด โ ์ฒซ ์ ๊ทผ๋ง 100ns,
๋๋จธ์ง 15๊ฐ๋ ์บ์ ํํธ ~1ns
vector ์ํ ๋ถ์:
1
2
3
std::vector<int> v(1'000'000);
long sum = 0;
for (int x : v) sum += x;
1
2
3
4
5
6
7
์ฒ์ ์ ๊ทผ: ์บ์ ๋ฏธ์ค โ DRAM์์ 64B ๊ฐ์ ธ์ด (16๊ฐ int) โ 100ns
๋ค์ 15๊ฐ: ์บ์ ํํธ โ 1ns ร 15 = 15ns
+ ํ๋ฆฌํ์ฒ๊ฐ ๋ค์ ๋ผ์ธ์ ๋ฏธ๋ฆฌ ๊ฐ์ ธ์ด (์ค์ ๋ก 0ns)
๋ค์ ๋ฏธ์ค: ํ๋ฆฌํ์ฒ ๋๋ถ์ ๊ฑฐ์ ์ ์ผ์ด๋จ โ
ํ๊ท ๋น์ฉ: ~6 ns/์์ ๋๋ ๊ทธ ์ดํ
1M ์ํ: ~1 ms
4-3. ๊ณต๊ฐ ์ง์ญ์ฑ (Spatial Locality)
โ๋ฐฉ๊ธ ์ ๊ทผํ ์ฃผ์ ๊ทผ์ฒ์ ๋ฐ์ดํฐ๋ ๊ณง ์ฌ์ฉ๋ ๊ฐ๋ฅ์ฑ์ด ๋๋คโ
CPU ์บ์ ์ค๊ณ์ ๊ฐ์ฅ ๊ฐ๋ ฅํ ๊ฐ์ . vector๋ ์ด ๊ฐ์ ์ ์๋ฒฝํ ๋ง์กฑ์ํต๋๋ค.
1
2
3
for (int i = 0; i < 1000000; ++i)
sum += v[i]; // i, i+1, i+2 ... ๊ฐ ์ฐ์ ์ฃผ์
// โ ํ ๋ผ์ธ์ 16๊ฐ์ฉ ๋ค์ด์ ์ฒ๋ฆฌ๋จ
list๋ ์ ๋ฐ๋์ ๋๋ค:
1
2
3
for (auto& x : list) // ๋
ธ๋ ์ฃผ์๊ฐ ๋ฌด์์
sum += x; // ๊ฐ ๋
ธ๋๋ง๋ค ์ ๋ผ์ธ ๋ก๋
// โ 1M ๋
ธ๋ = 1M ์บ์ ๋ฏธ์ค ๊ฐ๋ฅ์ฑ
list ์ํ ๋ถ์:
1
2
3
4
๊ฐ ๋
ธ๋ ์ ๊ทผ: ์บ์ ๋ฏธ์ค ๊ฐ๋ฅ์ฑ ๋งค์ฐ ๋์ (๋
ธ๋๊ฐ ๋ถ์ฐ๋จ)
โ 100ns ร 1M = 100ms โ
์ดํฉ: ~100 ms (vector ๋๋น ~100๋ฐฐ)
4-4. ์๊ฐ ์ง์ญ์ฑ (Temporal Locality)
โ๋ฐฉ๊ธ ์ฌ์ฉํ ๋ฐ์ดํฐ๋ ๊ณง ๋ค์ ์ฌ์ฉ๋ ๊ฐ๋ฅ์ฑ์ด ๋๋คโ
์บ์๋ LRU ๋น์ทํ ์ ์ฑ ์ผ๋ก ์ต๊ทผ ์ฌ์ฉ ๋ฐ์ดํฐ๋ฅผ ์ ์งํฉ๋๋ค. ์ด์ค ๋ฃจํ๋ ์์ ๋ฐ์ดํฐ ๋ฐ๋ณต ์ฌ์ฉ์ ํจ๊ณผ์ .
1
2
3
4
// ์๊ฐ ์ง์ญ์ฑ์ด ์ข์ ์ฝ๋
for (int iter = 0; iter < 100; ++iter)
for (int i = 0; i < 1000; ++i) // ๊ฐ์ 1000๊ฐ ๋ฐ์ดํฐ ๋ฐ๋ณต โ L1์ ์์ฃผ
v[i] = process(v[i]);
4-5. ํ๋์จ์ด ํ๋ฆฌํ์ฒ (Hardware Prefetcher)
CPU์๋ โ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด์ ๊ฐ์งํด ๋ค์ ๋ผ์ธ์ ๋ฏธ๋ฆฌ ๊ฐ์ ธ์ค๋ ํ๋กโ๊ฐ ์์ต๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
์์ฐจ ํจํด ๊ฐ์ง ์:
CPU๊ฐ ๋ผ์ธ N์ ์ฝ์ผ๋ฉด โ ํ๋ก๊ฐ N+1์ ๋ฏธ๋ฆฌ ์์ฒญ
CPU๊ฐ ๋ผ์ธ N+1์ ์ฝ์ผ๋ฉด โ ํ๋ก๊ฐ N+2๋ฅผ ์ด๋ฏธ ๊ฐ์ ธ์จ ์ํ
โ ๋ฉ๋ชจ๋ฆฌ ์ง์ฐ์ด ์ฌ์ค์ ์ฌ๋ผ์ง โ
์คํธ๋ผ์ด๋ ํจํด ๊ฐ์ง ์:
v[0], v[16], v[32], ... โ ์ผ์ ๊ฐ๊ฒฉ ๊ฐ์ง โ ๋ฏธ๋ฆฌ ๋ก๋
๋ฌด์์ ์ ๊ทผ:
list ๋
ธ๋ next ํฌ์ธํฐ ๋ฐ๋ผ๊ฐ๊ธฐ โ ํจํด ์์ โ ํ๋ฆฌํ์ฒ ๋ฌด๋ ฅ
โ DRAM 100ns ร N๋ฒ ๊ทธ๋๋ก ๋ถ๋ด
vector๊ฐ ๋น ๋ฅธ ์ด์ ์ ์ ๋ฐ์ ํ๋ฆฌํ์ฒ ๋๋ถ์ด๋ผ ํด๋ ๊ณผ์ฅ์ด ์๋๋๋ค.
4-6. ์๊ฐํ โ ์บ์ ๋ผ์ธ ์ ์ ์ฐจ์ด
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
vector<int>๊ฐ ์บ์ ๋ผ์ธ์ ์ฑ์ฐ๋ ๋ชจ์ต:
L1 ์บ์ ๋ผ์ธ (64B):
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ v[0] v[1] v[2] v[3] v[4] v[5] ... v[15] โ
โ 4B 4B 4B 4B 4B 4B 4B โ โ 16๊ฐ ์ ์๊ฐ ํ ๋ผ์ธ์
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โฒ 1๋ฒ ๋ฏธ์ค๋ก 16๊ฐ ์ฒ๋ฆฌ ๊ฐ๋ฅ
list<int> ๋
ธ๋๊ฐ ์บ์ ๋ผ์ธ์ ์ฐจ์งํ๋ ๋ชจ์ต:
L1 ์บ์ ๋ผ์ธ #1 (๋
ธ๋ A ์์น):
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ A.prev A.next A.data โโโโโโโโโโ (๋ค๋ฅธ ํ ๋ฐ์ดํฐ) โโโโโโโ
โ 8B 8B 4B โ 20B ์ฌ์ฉ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
L1 ์บ์ ๋ผ์ธ #2 (์ด๋๊ฐ ๋ฉ๋ฆฌ, ๋
ธ๋ B ์์น):
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โโโโโโ B.prev B.next B.data โโโโโโโโโโโโโโโโโโโโโโโโโ
โ 8B 8B 4B โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โฒ ๋งค ๋
ธ๋๋ง๋ค 1๋ฒ ๋ฏธ์ค โ 16๋ฐฐ ๋ ๋ง์ ๋ฏธ์ค
โฒ ๋ฐ์ดํฐ 4B๋ฅผ ์ํด 64B ๋ผ์ธ ํ ์ค์ ํต์งธ๋ก ๊ฐ์ ธ์ค๋ ์
โ ์บ์ ํจ์จ ~6%
4-7. ๋ฒค์น๋งํฌ ์ฌํด์
3์ฅ์์ ๋ณธ Stroustrup ๋ฒค์น๋งํฌ์ 100๋ฐฐ ์ฐจ์ด๋ฅผ ์บ์๋ก ๋ถ์ํ๋ฉด:
1
2
3
4
5
6
vector 1M ์ํ: ์บ์ ๋ฏธ์ค ~62,500ํ (1M / 16) ร 100ns = ~6.25 ms
+ ํ๋ฆฌํ์ฒ๋ก ์ ๋ฐ ์ด์ ํก์ โ ~1 ms ์ค์ธก
list 1M ์ํ: ์บ์ ๋ฏธ์ค ~1,000,000ํ ร 100ns = ~100 ms ์ค์ธก
โ ๊ฑฐ์ ๊ทธ๋๋ก ๋ถ๋ด
๋ฐฐ์ : ~100๋ฐฐ โ ์ธก์ ๊ฐ๊ณผ ์ผ์น
์ด๊ฒ ์๊ณ ๋ฆฌ์ฆ ๋ณต์ก๋ ๋ถ์์ผ๋ก๋ ์ ๋ ์ ๋ณด์ด๋ 100๋ฐฐ ๊ฒฉ์ฐจ์ ์ ์ฒด์ ๋๋ค.
4-8. ์ค์ ๊ด์ฉ๊ตฌ โ โ์บ์ ์นํ ์ฐ์ โ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Bad โ list๋ก ์์ฃผ ์ํ
std::list<Entity> entities;
for (auto& e : entities) e.update(); // ์บ์ ๋ฏธ์ค ํญํ
// Good โ vector๋ก ์ฐ์ ์๋
std::vector<Entity> entities;
for (auto& e : entities) e.update(); // SoA๋ฅผ ๋ ์ ์ฉํ๋ฉด ๋ ๋น ๋ฆ
// Better โ Structure of Arrays (SoA) ํจํด
struct EntitySystem {
std::vector<Vec3> positions;
std::vector<Vec3> velocities;
std::vector<float> hps;
// ์์น ์
๋ฐ์ดํธ๋ positions/velocities๋ง ์ํ โ ๋ ํฐ ์บ์ ํจ์จ
};
๊ฒ์ ์์ง(Unreal, Unity DOTS, Bevy ๋ฑ)์ด ECS(Entity Component System)๋ก SoA๋ฅผ ์ฑํํ๋ ์ด์ ์ ์ ๋ฐ์ด ์ด ์บ์ ์นํ์ฑ ๋๋ฌธ์ ๋๋ค.
5. iterator ๋ฌดํจํ / ์์ธ ์์ ์ฑ / ๋ฉ๋ชจ๋ฆฌ ํจ์จ
5-1. iterator ๋ฌดํจํ ๊ท์น
vector
| ์ฐ์ฐ | ๋ฌดํจํ ๋ฒ์ |
|---|---|
push_back, emplace_back | ์ฌํ ๋น ์ ๋ชจ๋ iterator/ํฌ์ธํฐ/์ฐธ์กฐ ๋ฌดํจ |
insert(pos, ...) | ์ฌํ ๋น ์ ์ ๋ถ, ์๋๋ฉด pos ์ดํ ๋ชจ๋ |
erase(pos) | pos ์ดํ ๋ชจ๋ |
clear() | ๋ชจ๋ (end๋ ํฌํจ) |
reserve(n) (n > capacity) | ๋ชจ๋ |
shrink_to_fit() | ์ ์ฌ์ ์ผ๋ก ๋ชจ๋ |
resize | ์ ์ฌ์ ์ผ๋ก ๋ชจ๋ |
1
2
3
4
5
std::vector<int> v = {1, 2, 3};
auto it = v.begin(); // it โ &v[0]
v.push_back(4); // ์ฌํ ๋น ๋ฐ์ ๊ฐ๋ฅ โ it ๋ฌดํจํ ๊ฐ๋ฅ!
std::cout << *it; // โ UB (์ด์ด ์ข์ ๋์ํ ์๋, ํฌ๋์ํ ์๋)
list
| ์ฐ์ฐ | ๋ฌดํจํ ๋ฒ์ |
|---|---|
push_back/push_front | ๋ฌดํจํ ์์ โ |
insert(pos, ...) | ๋ฌดํจํ ์์ โ |
erase(pos) | ์ญ์ ๋ ๋ ธ๋๋ง โ |
splice (๋ค๋ฅธ list๋ก ๋
ธ๋ ์ด๋) | ๋ฌดํจํ ์์ (iterator๋ ์ list์์ ์ ํจ) |
clear() | ๋ชจ๋ |
merge, sort | ์์ (๋ ธ๋ ์๋ฆฌ๋ง ๋ฐ๋, iterator ์ ํจ) |
1
2
3
4
5
6
7
std::list<int> l = {1, 2, 3};
auto it = std::next(l.begin()); // it โ 2
l.push_back(4); // โ
it ๊ทธ๋๋ก ์ ํจ
l.push_front(0); // โ
it ๊ทธ๋๋ก ์ ํจ
l.insert(l.begin(), -1); // โ
it ๊ทธ๋๋ก ์ ํจ
*it; // โ
2 โ ์์
์ด ๋ ธ๋ ์์ ์ฑ์ด list์ ๊ฑฐ์ ์ ์ผํ๊ฒ ์ ์งํ ์ด์ ์ ๋๋ค. ๋ค๋ฅธ ์๋ฃ๊ตฌ์กฐ์ iterator/ํฌ์ธํฐ๋ฅผ ์ ์ฅํด ๋๊ณ ์ถ์ ๋ ์ ์ฉ.
5-2. ์์ธ ์์ ์ฑ (Exception Safety)
๋ณด์ฅ ๋จ๊ณ ๋ณต์ต
| ๋จ๊ณ | ์๋ฏธ |
|---|---|
| No-throw | ์ ๋ ์์ธ ๋์ง์ง ์์ |
| Strong | ์์ธ ๋ฐ์ ์ ์ํ ๋ถ๋ณ (๋กค๋ฐฑ) |
| Basic | ์์ธ ๋ฐ์ํด๋ ์์ ๋์ ์์, ์ํ๋ ์ผ๊ด์ฑ ์์ |
| No guarantee | ์ ์ด๋ ๊ฒ๋ ๋ณด์ฅ ์ ๋จ |
vector์ ์์ธ ์์ ์ฑ
1
2
3
std::vector<Widget> v;
v.push_back(w); // ์ฌํ ๋น ์ ๊ธฐ์กด ์์๋ค์ ์ ๋ฒํผ๋ก ์ฎ๊ฒจ์ผ ํจ
// โ ์ฎ๊ธฐ๋ ๋์ค ์์ธ๊ฐ ๋ฐ์ํ๋ฉด?
- Widget์ด
noexcept์ด๋ ์์ฑ์๋ฅผ ๊ฐ์ง๋ฉด โ vector๋ move๋ฅผ ์ฌ์ฉํด strong guarantee ์ ๊ณต - Widget์ ์ด๋ ์์ฑ์๊ฐ throw ๊ฐ๋ฅํ๋ฉด โ vector๋ ์์ ์ ์ํด copy ์ฌ์ฉ (๋๋ฆผ) โ strong guarantee ๊ฐ๋ฅ
- ๋ณต์ฌ ์์ฑ์๋ throwํ๋ฉด โ basic guarantee๋ก ๊ฐ๋ฑ
1
2
3
4
class Widget {
public:
Widget(Widget&&) noexcept; // โ
์ด๊ฒ ์์ด์ผ vector๊ฐ ๋น ๋ฅธ strong guarantee ์ฌ์ฉ
};
list์ ์์ธ ์์ ์ฑ
push_back/push_front/insert๋ strong guarantee ์๋ (์ ๋ ธ๋ ํ ๋น๋ง ์คํจํ๋ฉด list๋ ๋ณ๊ฒฝ ์์)- ๋ ธ๋ ๋จ์๋ผ ์ด๋ ๋น์ฉ๋ ์๊ณ ๋กค๋ฐฑ๋ ๋จ์
- ์ด๊ฒ list์ ๋ ๋ค๋ฅธ ์ ์งํ ์ด์
5-3. ๋ฉ๋ชจ๋ฆฌ ํจ์จ
| ํญ๋ชฉ | vector | list |
|---|---|---|
| ๋ ธ๋๋น ์ค๋ฒํค๋ | 0 (capacity ์ฌ์ ๋ถ ์ผ๋ถ) | prev 8B + next 8B + ํ ํค๋ ~16B = 32B+ |
| ํ ๋น์ ํธ์ถ | 1ํ (๋๋ reserve๋ก 0ํ) | ๋ ธ๋๋น 1ํ |
| ๋ฉ๋ชจ๋ฆฌ ๋จํธํ | ๊ฑฐ์ ์์ | ์ฌ๊ฐ (์์ ๋ธ๋ก ๋๋ ๋ฐ์) |
| ๋ฐ์ดํฐ ํจ์จ (int ๊ธฐ์ค) | ~95%+ | ~10% (4B ๋ฐ์ดํฐ / 40B ๋ ธ๋) |
| TLB ์๋ฐ | ๋ฎ์ (์ฐ์ ํ์ด์ง) | ๋์ (๋ถ์ฐ ํ์ด์ง) |
int 1,000,000๊ฐ:
- vector: ์ฝ 4 MB
- list: ์ฝ 40 MB
big object์ผ์๋ก ์ฐจ์ด๊ฐ ์ค์ง๋ง, ๋ณดํต 1~3๋ฐฐ ๋ฉ๋ชจ๋ฆฌ ์ฐจ์ด๋ ํญ์ ์์ต๋๋ค.
5-4. ๋ค๋ฅธ ์ฐจ์ด ์ข ํฉํ
| ย | vector | list |
|---|---|---|
| ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์ | ์ฐ์ | ๋ถ์ฐ ๋ ธ๋ |
| ์์ ์ ๊ทผ | O(1) | O(n) |
| ์์ฐจ ์ํ (์ค์ธก) | ๋งค์ฐ ๋น ๋ฆ | ๋งค์ฐ ๋๋ฆผ |
| ๋ push (์ค์ธก) | ๋งค์ฐ ๋น ๋ฆ | ๋ณดํต |
| ์ค๊ฐ ์ฝ์ (์์น ์ ๋) | O(n), ์บ์๋ก ๋น ๋ฆ | O(1), ํ ๋น์ผ๋ก ๋๋ฆด ์ ์์ |
| iterator ์์ ์ฑ | ์ฝํจ (์ฌํ ๋น ์ํ) | ๊ฐํจ (์ญ์ ๋ ธ๋๋ง ๋ฌดํจ) |
| ์์ธ ์์ ์ฑ (push) | ์กฐ๊ฑด๋ถ strong | ์๋ strong |
| ๋ฉ๋ชจ๋ฆฌ ์ค๋ฒํค๋ | ์์ | ํผ (๋ ธ๋๋น 32B+) |
| ์บ์ ์นํ์ฑ | โ โ โ โ โ | โ |
| ๊ถ์ฅ๋ | ๊ธฐ๋ณธ ์ ํ | ๊ฑฐ์ ์ ์ |
6. ์ธ์ list๋ฅผ ์จ์ผ ํ๋ โ ์ฌ์ค์ ๊ฑฐ์ ์์
ํต์ฌ ํ ๋ฌธ์ฅ
ํ๋ ํ๋์จ์ด์์
std::list๋ ๊ฑฐ์ ํญ์ ์๋ชป๋ ์ ํ์ ๋๋ค. ์ ๋นํ๋๋ ์ผ์ด์ค๋ ๊ทนํ ์ข๊ณ , ๊ทธ๋ง์ ๋ ๋ณดํต ๋ค๋ฅธ ์๋ฃ๊ตฌ์กฐ๋ก ๋์ฒด ๊ฐ๋ฅํฉ๋๋ค.
6-1. list๊ฐ ์ ๋นํ๋๋ ๋๋ฌธ ์ผ์ด์ค
1
2
3
4
5
6
์กฐ๊ฑด (๋ชจ๋ ๋ง์กฑํด์ผ ํจ):
1) ๋งค์ฐ ํฐ ๊ฐ์ฒด (์ KB ์ด์) โ ์ด๋ ๋น์ฉ์ด ์ง์ง ํฐ ๊ฒฝ์ฐ
2) ์ฆ์ splice/merge โ ๋
ธ๋ ์ฌ๋ฐฐ์น๊ฐ ์ฃผ ์์
3) iterator/ํฌ์ธํฐ ์์ ์ฑ์ด ์ ๋์ ํ์ โ ์ธ๋ถ ๊ตฌ์กฐ์ ์ ์ฅํด์ผ ํจ
4) ๊ฒ์์ ๊ฑฐ์ ์ ํจ โ ์์น iterator๋ฅผ ํญ์ ์์ ๋ค๊ณ ์์
5) ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ ๊ฒฝ ์ ์
์ด 5๊ฐ์ง๊ฐ ๋ชจ๋ ์ถฉ์กฑ๋๋ ๊ฒฝ์ฐ๋ ์ค๋ฌด์์ ๋งค์ฐ ๋๋ญ
๋๋ค. ํ๋๋ผ๋ ๋น ์ง๋ฉด vector(๋๋ vector
6-2. ๋ ์์ฃผ ์ ํฉํ ๋์ โ std::deque
vector์ list์ ์ ์ถฉ์์ ๋๋ค.
1
2
3
4
5
6
7
8
9
10
deque ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์:
chunk 0 (4KB) chunk 1 (4KB) chunk 2 (4KB)
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
โ [.][.][a][b][c] โ โ [d][e][f][g][h] โ โ [i][j][k][.][.] โ
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
โ โ
front back
์ง์ ์ธ๋ฑ์ฑ ๊ฐ๋ฅ (chunk ์ธ๋ฑ์ค + ์์์ ์คํ์
) โ O(1) ์์ ์ ๊ทผ
| ํน์ฑ | vector | deque | list |
|---|---|---|---|
| ์์ ์ ๊ทผ | O(1) ๋น ๋ฆ | O(1) ์ฝ๊ฐ ๋๋ฆผ | O(n) |
| push_back | amortized O(1) | O(1) (์ฌํ ๋น ๊ฑฐ์ ์์) | O(1) |
| push_front | O(n) | O(1) โ | O(1) |
| ์บ์ ์นํ | ์ต๊ณ | ๋ณดํต (์ฒญํฌ ์์์๋ง) | ์ต์ |
| iterator ์์ ์ฑ | ์ฝํจ | ์ฝํจ (front/back push๋ง ์์ ) | ๊ฐํจ |
| ๋ฉ๋ชจ๋ฆฌ ํจ์จ | ์ต๊ณ | ๋ณดํต | ์ต์ |
deque ์ถ์ฒ ์ผ์ด์ค:
- push_front์ push_back์ด ๋ชจ๋ ์์ฃผ ํ์ (queue)
- ํฐ ์ปจํ ์ด๋์ธ๋ฐ ์ฌํ ๋น์ ์ด๋ ๋น์ฉ์ด ๋ถ๋ด๋จ
- ํ์ค
std::queue/std::stack์ ๊ธฐ๋ณธ ์ปจํ ์ด๋๋ก deque ์ฌ์ฉ
6-3. ๋ ๋์ ๋์ โ vector<unique_ptr<T>>
ํฐ ๊ฐ์ฒด + iterator ์์ ์ฑ์ด ํ์ํ ๊ฒฝ์ฐ, ์ง์ง ๋ต์ ๋ณดํต ์ด ํจํด์ ๋๋ค.
1
2
3
4
5
6
7
8
struct HugeNode { char payload[4096]; };
std::vector<std::unique_ptr<HugeNode>> nodes;
// vector ์์ฒด๋ ํฌ์ธํฐ 8B๋ง ์ด๋ โ ์บ์ ์นํ + ์ด๋ ๋น ๋ฆ
// ๊ฐ์ฒด ์์ฒด๋ ํ์ ๊ณ ์ โ ํฌ์ธํฐ/์ฐธ์กฐ ์์ ์ฑ (์ฌํ ๋นํด๋ *p๋ ์ ํจ)
HugeNode* p = nodes[42].get();
nodes.push_back(std::make_unique<HugeNode>()); // ์ฌํ ๋น๋ผ๋ p๋ ์ ํจ โ
์ฅ์ :
- ์ปจํ ์ด๋ ์ํ๋ ๋น ๋ฆ (ํฌ์ธํฐ๋ง ์ํ)
- ๊ฐ์ฒด๋ ํ์ ๊ณ ์ โ ์ธ๋ถ์์ ์์ ํ๊ฒ ์ฐธ์กฐ ๊ฐ๋ฅ
- list์ ๋ชจ๋ ์ฅ์ + vector์ ์บ์ ์นํ์ฑ
11๋ฒ [์ค๋งํธ ํฌ์ธํฐ] ์ ์์ฐ์ค๋ฝ๊ฒ ์ฐ๊ฒฐ๋๋ ํจํด์ ๋๋ค.
6-4. std::forward_list ๋น๊ต
C++11์์ ์ถ๊ฐ๋ ๋จ๋ฐฉํฅ ์ฐ๊ฒฐ ๋ฆฌ์คํธ.
1
2
3
4
struct ForwardNode {
ForwardNode* next; // prev ์์ โ 8๋ฐ์ดํธ ์ ์ฝ
T data;
};
- ๋ ธ๋๋น 8B ์ ์ฝ (prev ํฌ์ธํฐ ์ ๊ฑฐ)
size()๋ฉค๋ฒ ํจ์ ์์ (์ฑ๋ฅ ์ํด)- ์๋ฒ ๋๋/๋ฉ๋ชจ๋ฆฌ ์ ์ฝ ํ๊ฒฝ์์ ๊ฐ๋ ์ ๋นํ
- ์ผ๋ฐ ๋ฐ์คํฌํฑยท์๋ฒยท๊ฒ์์์๋ ์ฌ์ ํ vector๊ฐ ์ ๋ฆฌ
6-5. โVector Firstโ ์์น
์ ๊ณ ๊ถ์์๋ค์ด ๊ฑฐ์ ๋ง์ฅ์ผ์น๋ก ์ถ์ฒ:
- Bjarne Stroustrup (C++ ์ฐฝ์์): โUse
vector. Donโt uselistunless you have a very specific reason.โ - Herb Sutter (C++ Standards Committee): โIf youโre not sure, use
vector.โ - Sean Parent (Adobe principal): โNo raw loops. No raw owners. Default container is
vector.โ
โ์ฑ๋ฅ์ด ์์ฌ์ค๋ฌ์ด ์ํฉ์์๋ ์ธก์ ํ๊ธฐ ์ ์ vector๋ก ์์ํ๋ผ. list๋ก ๋ฐ๊ฟ ์ด์ ๋ ์ธก์ ์ด list๊ฐ ๋ ๋น ๋ฆ์ ์ฆ๋ช ํ ํ์์ผ ์๊ธด๋ค.โ
์ด๊ฒ 13๋ฒ ์ฃผ์ ์ ๊ฐ์ฅ ์ค์ํ ํ ์ค ๊ฒฐ๋ก ์ ๋๋ค.
7. ์ธ๋ฆฌ์ผ TArray vs STL
ํต์ฌ ํ ๋ฌธ์ฅ
์ธ๋ฆฌ์ผ์
TArray๋ฅผ vector ๋์์ 1๊ธ ์๋ฏผ์ผ๋ก ๋๊ณ ,std::list๋์ ์๋ฃ๊ตฌ์กฐ๋ ์๋์ ์ผ๋ก 1๊ธ์ผ๋ก ๋์ง ์์์ต๋๋ค. ์บ์ ์นํ ์ฒ ํ์ด ๊ฒ์ ์์ง์์ ๋ ๊ฐํ๊ฒ ์ ์ฉ๋ฉ๋๋ค.
7-1. TArray<T> โ ์ธ๋ฆฌ์ผํ vector
1
2
3
4
5
6
7
8
9
10
11
TArray<int32> Arr;
Arr.Add(10); // std::vector::push_back ๋์
Arr.Insert(20, 0); // std::vector::insert ๋์
Arr.RemoveAt(0); // std::vector::erase ๋์
Arr.RemoveAtSwap(0); // ๋ง์ง๋ง ์์์ swap ํ pop_back โ O(1) ๋น ๋ฅธ ์ญ์
int32 V = Arr[0]; // ์์ ์ ๊ทผ
// Reserve / SetNum
Arr.Reserve(1000); // std::vector::reserve ๋์
Arr.SetNum(500); // resize ๋์
Arr.Empty(); // clear ๋์
๋ด๋ถ ๊ตฌ์กฐ๋ std::vector์ ๊ฑฐ์ ๋์ผ:
- ์ฐ์ ๋ฉ๋ชจ๋ฆฌ ๋์ ๋ฐฐ์ด
- ์ฑ์ฅ ์ธ์ ๋ณดํต 1.5x ~ 2x (DefaultAllocator)
- ์บ์ ์นํ
7-2. UPROPERTY ยท GC ํตํฉ
1
2
3
4
5
6
7
UCLASS()
class AMyActor : public AActor {
GENERATED_BODY()
public:
UPROPERTY()
TArray<UItem*> Items; // GC๊ฐ ๋ชจ๋ ์์ ์ถ์ , ๋ฆฌํ๋ ์
๋
ธ์ถ
};
UPROPERTY()๋ก ์ ์ธํ๋ฉด GC๊ฐ ์ปจํ ์ด๋ ์ UObject๊น์ง ์๋ ์ถ์ - ๋ธ๋ฃจํ๋ฆฐํธ ๋ ธ์ถ, ๋ํ ์ผ ํจ๋ ํธ์ง, replication ์ง์
std::vector<UItem*>์ GC๊ฐ ์ถ์ ๋ชป ํจ โ ์ธ๋ฆฌ์ผ์์๋ ์ ๋ ์ฐ์ง ์์
7-3. TArray::RemoveAt vs RemoveAtSwap
1
2
3
4
5
6
7
TArray<int32> Arr = {1, 2, 3, 4, 5};
// ์์ ์ญ์ (์์ ์ ์ง) โ std::vector::erase์ ๋์ผ, O(n)
Arr.RemoveAt(1); // {1, 3, 4, 5}
// ๋น ๋ฅธ ์ญ์ (์์ ๊นจ์ง) โ O(1)
Arr.RemoveAtSwap(1); // {1, 5, 3, 4} โ ๋ง์ง๋ง ์์๋ฅผ ๊ทธ ์๋ฆฌ์
์์๊ฐ ์ค์ํ์ง ์์ ์ปจํ
์ด๋(ํํฐํด, ์ ๋ฆฌ์คํธ ๋ฑ)๋ RemoveAtSwap์ด ํจ์ฌ ๋น ๋ฆ
๋๋ค โ ์ด๊ฒ ๊ฒ์ ์์ง ์ปจํ
์ด๋์ ์ฑ๋ฅ ๋ํ
์ผ.
7-4. ์ธ๋ฆฌ์ผ์ list ๋์์ด (์ฌ์ค์) ์๋ ์ด์
1
2
3
4
// ํ์ค std::list ์ง์ ๋์์ ์์
// ํฌํผ ์์ค์ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ ์กด์ฌ:
TLinkedList<T> // ๋จ๋ฐฉํฅ ์ฐ๊ฒฐ
TDoubleLinkedList<T> // ์ด์ค ์ฐ๊ฒฐ
์ด๋ค์:
- intrusive ์คํ์ผ์ ๊ฐ๊น๊ฑฐ๋ ๋งค์ฐ ๋จ์ํ ๊ตฌํ
- ๊ฒ์ ์์ง์ด list๋ฅผ ๊ถ์ฅํ์ง ์๋๋ค๋ ๊ฐํ ์๋ ํํ
- ๋๋ถ๋ถ ์ฝ๋๋
TArray๋๋TMap(ํด์๋งต)์ผ๋ก ์์ฑ๋จ
7-5. ์ธ๋ฆฌ์ผ ์ปจํ ์ด๋ vs STL ์ข ํฉํ
| ์นดํ ๊ณ ๋ฆฌ | STL | ์ธ๋ฆฌ์ผ | ๋น๊ณ |
|---|---|---|---|
| ๋์ ๋ฐฐ์ด (vector) | std::vector | TArray | 1๊ธ ์๋ฏผ, GC ํตํฉ |
| ์ ์ ๋ฐฐ์ด | std::array | TStaticArray | ์ปดํ์ผ ํ์ size |
| ์ฐ๊ฒฐ ๋ฆฌ์คํธ (list) | std::list | TLinkedList (ํฌํผ) | 1๊ธ ์๋ |
| ๋จ๋ฐฉํฅ ๋ฆฌ์คํธ | std::forward_list | (์์) | ย |
| ๋๋ธ์๋ ํ (deque) | std::deque | TQueue, TCircularQueue | ๋ฉํฐ์ค๋ ๋ ์์ ์ต์ |
| ํด์๋งต | std::unordered_map | TMap | open addressing ๋ณํ |
| ํธ๋ฆฌ๋งต | std::map | (์์, TSortedMap) | RB ํธ๋ฆฌ ๊ฑฐ์ ์ ์ |
| ํด์์ | std::unordered_set | TSet | ย |
| ๋ฌธ์์ด | std::string | FString, FName, FText | ๋ค์ธต ๋ถ๋ฆฌ |
| ์ค๋งํธ ํฌ์ธํฐ | unique_ptr/shared_ptr | TUniquePtr/TSharedPtr | 11๋ฒ ์ฐธ๊ณ |
์ธ๋ฆฌ์ผ์ vectorยทhashmapยทhashset ์ค์ฌ์ด๊ณ ํธ๋ฆฌ/์ฐ๊ฒฐ๋ฆฌ์คํธ๋ ๊ฑฐ์ ์ฐ์ง ์์ต๋๋ค. ์ด๊ฒ ๊ฒ์ ์์ง์ ์บ์ ์นํ ์ฒ ํ.
7-6. Algo:: โ STL <algorithm> ๋์
1
2
3
4
5
TArray<int32> Arr = {3, 1, 4, 1, 5, 9, 2, 6};
Algo::Sort(Arr); // std::sort ๋์
int32* P = Algo::Find(Arr, 5); // std::find ๋์
Algo::Reverse(Arr); // std::reverse ๋์
๋ด๋ถ์ ์ผ๋ก STL๊ณผ ๋์ผํ ์ ๋ ฌ ์๊ณ ๋ฆฌ์ฆ(introsort ๋ณํ)์ด์ง๋ง ์ธ๋ฆฌ์ผ ๋ฉ๋ชจ๋ฆฌ ์์คํ ๊ณผ ํตํฉ.
8. ํ๊ท ๋ค๋ฆฌ โ ๋ค๋ฅธ CS ํ์ผ ์ฐ๊ฒฐ
8-1. 11๋ฒ [์ค๋งํธ ํฌ์ธํฐ]์์ ์ฐ๊ฒฐ
vector<unique_ptr<T>> ํจํด
1
2
3
4
5
6
7
8
std::vector<std::unique_ptr<Widget>> widgets;
widgets.push_back(std::make_unique<Widget>(1));
widgets.push_back(std::make_unique<Widget>(2));
// vector ์์ฒด๋ ํฌ์ธํฐ 8B๋ง ์ด๋ โ ์บ์ ์นํ (vector์ ์ฅ์ )
// ๊ฐ์ฒด๋ ํ์ ๊ณ ์ โ ํฌ์ธํฐ ์์ ์ฑ (list์ ์ฅ์ )
// ๋ฉ๋ชจ๋ฆฌ ๋์ ์์ โ RAII (์ค๋งํธ ํฌ์ธํฐ์ ์ฅ์ )
์ด ํจํด์ 13๋ฒ์์ ๋ณธ โvector์ ์บ์ ์นํ + list์ ์์ ์ฑ์ ๋ ๋ค ๊ฐ์ง๋ ๋ฒ ์คํธ ํจํดโ ์ ๋๋ค.
vector<shared_ptr<T>> ์ฃผ์์
1
2
std::vector<std::shared_ptr<Widget>> w1 = ...;
std::vector<std::shared_ptr<Widget>> w2 = w1; // ๋ชจ๋ ์์์ atomic refcount++
- vector ๋ณต์ฌ ์ ๋ชจ๋ ์์์ ์ฐธ์กฐ ์นด์ดํธ๊ฐ atomic ์ฆ๊ฐ โ ํฐ ๋น์ฉ
- shared_ptr์ด atomic์ด๋ผ๋ ๋น์ฉ(11๋ฒ)์ด vector ์์์ N๋ฐฐ ์ฆํญ๋จ
- ์ง์ง ๊ณต์ ๊ฐ ํ์ํ๋ฉด
vector<shared_ptr>, ์๋๋ฉดvector<unique_ptr>๋๋vector<T>์ง์
8-2. 12๋ฒ [๋ณต์ฌ ๊ธ์งยทmove-only]์์ ์ฐ๊ฒฐ
vector์์ move ์๋ฏธ๋ก ์ ์ค์์ฑ
1
2
3
4
std::vector<Widget> v;
v.reserve(10);
for (int i = 0; i < 1000; ++i)
v.push_back(Widget()); // ์ฌํ ๋น ์ ๊ธฐ์กด ์์๋ฅผ ์ ๋ฒํผ๋ก ์ฎ๊ฒจ์ผ ํจ
- Widget์ด
noexceptmove ์์ฑ์๋ฅผ ๊ฐ์ง๋ฉด โ vector๊ฐ move ์ฌ์ฉ โ ๋น ๋ฅด๊ณ strong guarantee - ์์ผ๋ฉด โ vector๊ฐ ์์ ์ ์ํด copy ์ฌ์ฉ โ ๋๋ฆผ
- ์ด๊ฒ 12๋ฒ์์ Rule of Five๊ฐ ์ค์ํ ์ด์ ์ ํต์ฌ ์ฌ๋ก
1
2
3
4
5
6
7
8
class Widget {
public:
Widget(Widget&&) noexcept; // โ
noexcept ํ์
Widget& operator=(Widget&&) noexcept;
Widget(const Widget&);
Widget& operator=(const Widget&);
~Widget();
};
move-only ํ์ ์ ์ปจํ ์ด๋์ ๋ด๊ธฐ
1
2
3
4
5
std::vector<std::unique_ptr<Widget>> v; // โ
move-only OK
std::vector<std::thread> threads; // โ
thread๋ move-only
// std::list๋ ๊ฐ๋ฅ:
std::list<std::unique_ptr<Widget>> l;
unique_ptr(12๋ฒ ์ฐธ๊ณ )์ ๋ณต์ฌ ๋ถ๊ฐ์ง๋ง vectorยทlist ๋ชจ๋ move๋ก ์ฒ๋ฆฌํด ์ปจํ
์ด๋ ์์ ์ ๋ค์ด๊ฐ๋๋ค.
8-3. 09๋ฒ [RAII]์์ ์ฐ๊ฒฐ
vector ์์ฒด๊ฐ RAII์ ์ ์ ์ฌ๋ก:
1
2
3
4
{
std::vector<int> v(1'000'000); // 4MB ์๋ ํ ๋น
// ... ์ฌ์ฉ
} // ์ค์ฝํ ์ข
๋ฃ โ ์๋ ํด์ , ๋์ ์์
- ์์ฑ์์์ ๋ฉ๋ชจ๋ฆฌ ํ๋
- ์๋ฉธ์์์ ๋ฉ๋ชจ๋ฆฌ ํด์ (์์ธ ๋ฐ์ํด๋ ๋ณด์ฅ)
- ์ฌ์ฉ์๊ฐ
delete[]์ ํธ์ถํ ํ์ ์์
์ด๊ฒ 9๋ฒ RAII์ 13๋ฒ ์ปจํ ์ด๋๊ฐ ์์ฐ์ค๋ฝ๊ฒ ์ด์ด์ง๋ ์ง์ .
8-4. 10๋ฒ [๋๊ธ๋ง ํฌ์ธํฐ]์์ ์ฐ๊ฒฐ
vector ์ฌํ ๋น์ด ๋๊ธ๋ง ํฌ์ธํฐ๋ฅผ ๋ง๋๋ ๊ฐ์ฅ ํํ ํจํด:
1
2
3
4
5
6
7
std::vector<int> v = {1, 2, 3};
int* p = &v[0]; // p โ v์ ์ฒซ ์์
v.push_back(4); // ์ฌํ ๋น ๊ฐ๋ฅ โ ์ ๋ฒํผ๋ก ์ด๋
// p๋ ์ด์ freed memory ๊ฐ๋ฆฌํด โ
*p = 99; // โ UB โ ๋๊ธ๋ง ํฌ์ธํฐ ์ญ์ฐธ์กฐ
- 10๋ฒ์์ ๋ณธ โ์ปจํ ์ด๋ ์ฌํ ๋น ํ ํฌ์ธํฐ ๋ฌดํจํโ ์ ์ ํํ ์ฌ๋ก
- ํด๊ฒฐ:
vector<unique_ptr<T>>๋ก ๊ฐ์ฒด ์์ ์ฑ ํ๋ณด (8-1 ์ฐธ๊ณ )
8-5. 04-28(์ค๋) ํ๊ณ โ 12๋ฒ โ 13๋ฒ ์์ฐ ํ๋ฆ
์ค๋ 12๋ฒ์์ ๋ค๋ฃฌ ๊ฐ๋ ์ด 13๋ฒ ์ปจํ ์ด๋์์ ์ด๋ป๊ฒ ํ์ฉ๋๋๊ฐ:
1
2
3
4
5
6
7
8
9
12๋ฒ ํต์ฌ ๊ฐ๋
13๋ฒ์์์ ํ์ฉ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Rule of Five (move ์์ฑ์) โ vector ์ฌํ ๋น ์ move ์ฌ์ฉ โ ์ฑ๋ฅ ๊ฒฐ์
move-only ํ์
(unique_ptr) โ vector<unique_ptr<T>> ํจํด โ ์์ ์ฑ+์บ์
์๋ฌต์ ์ญ์ โ unique_ptr ๋ฉค๋ฒ๋ฅผ ๊ฐ์ง ํด๋์ค๊ฐ ์๋
์ผ๋ก vector์์ move-only๋ก ๋์
๋ณต์ฌ ๊ธ์ง(ํ์ผ/๋ฎคํ
์ค/์์ผ) โ vector<ifstream>ยทvector<thread>์ฒ๋ผ
move-only ์ปจํ
์ด๋ ํ์ฉ
RAII (Rule of Zero) โ vector ์์ฒด๊ฐ RAII์ ๋ํ ์ฌ๋ก
13๋ฒ์ 12๋ฒ์ โ๋ณต์ฌยท์ด๋ ์๋ฏธ๋ก โ์ด ์ปจํ ์ด๋์์ ์ค์ ๋ก ์ด๋ป๊ฒ ์๋ํ๋์ง ๋ณด์ฌ์ฃผ๋ ์์ฉํธ์ ๋๋ค.
9. ๊ผฌ๋ฆฌ์ง๋ฌธ ์์ ๊ฒฝ๋ก
๋ฉ์ธ ์ง๋ฌธ ๋ต๋ณ ํ ์์ ํ๋ฆ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
"vector์ list์ ์ฐจ์ด๋?"
โ
โโ ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์ (์ฐ์ vs ๋ถ์ฐ)
โ โโ "์ฌํ ๋น์ ์ด๋ป๊ฒ ์ผ์ด๋๋์?"
โ โ โโ "์ฑ์ฅ ์ธ์๊ฐ 1.5๋ฐฐยท2๋ฐฐ์ธ ์ด์ ๋?"
โ โโ "list ๋
ธ๋ ํ๋์ ๋ฉ๋ชจ๋ฆฌ ํฌ๊ธฐ๋?"
โ
โโ ์๊ฐ ๋ณต์ก๋
โ โโ "list๋ O(1) ์ฝ์
์ธ๋ฐ ์ vector๋ณด๋ค ๋๋ฆฐ๊ฐ์?" โ
ํจ์
โ โ โโ "๊ทธ๋ผ list๊ฐ ๋ ๋น ๋ฅธ ๊ฒฝ์ฐ๋ ์ ๋ง ์๋์?"
โ โโ "amortized O(1)์ด ์ ํํ ๋ญ๊ฐ์?"
โ
โโ CPU ์บ์ (โ
๊ฐ์ฅ ๊น์ด ๋ค์ด๊ฐ ๊ฐ๋ฅ์ฑ ๋์)
โ โโ "์บ์ ๋ผ์ธ์ด ๋ญ๊ฐ์?"
โ โ โโ "๊ณต๊ฐ ์ง์ญ์ฑ๊ณผ ์๊ฐ ์ง์ญ์ฑ์ ์ฐจ์ด๋?"
โ โโ "ํ๋ฆฌํ์ฒ๊ฐ ๋ญ๊ฐ์?"
โ โ โโ "list์์๋ ์ ์๋ํ์ง ์๋์?"
โ โโ "L1ยทL2ยทL3 ์ฐจ์ด?"
โ
โโ iterator ๋ฌดํจํ
โ โโ "vector์์ push_back ํ iterator ์ฌ์ฉ์ ์์ ํ๊ฐ์?"
โ โโ "list๊ฐ iterator ์์ ์ฑ์ด ๊ฐํ ์ด์ ๋?"
โ
โโ ์์ธ ์์ ์ฑ
โ โโ "vector ์ฌํ ๋น ์ noexcept ์ด๋์ด ์ ์ค์ํ๊ฐ์?" โ
12๋ฒ ํ๊ท
โ
โโ ์ธ์ list?
โ โโ "deque์ ์ด๋ค ์ฐจ์ด๊ฐ ์๋์?"
โ โโ "vector<unique_ptr<T>>๊ฐ list ๋์์ธ ์ด์ ๋?" โ
11๋ฒ ํ๊ท
โ
โโ ์ธ๋ฆฌ์ผ
โโ "TArray์ std::vector์ ์ฐจ์ด๋?"
โโ "RemoveAt vs RemoveAtSwap?"
โโ "์ ์ธ๋ฆฌ์ผ์ list ๋์์ 1๊ธ์ผ๋ก ๋์ง ์๋์?"
๊ฐ ๊ผฌ๋ฆฌ์ง๋ฌธ 30์ด ๋ต๋ณ
Q: vector์ list์ ๊ฐ์ฅ ํฐ ์ฐจ์ด๋?
1
2
3
4
5
6
๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์:
vector โ ์ฐ์ ๋ฉ๋ชจ๋ฆฌ ๋์ ๋ฐฐ์ด
list โ ๋
ธ๋๊ฐ ํ์ ๋ถ์ฐ, prev/next ํฌ์ธํฐ๋ก ์ฐ๊ฒฐ
์ด ์ฐจ์ด๊ฐ ์บ์ ์นํ์ฑ์ ๊ฒฐ์ ํด ์ค์ธก ์ฑ๋ฅ์ 100๋ฐฐ๊น์ง ๊ฐ๋ฅด๊ณ ,
์ด๋ก ์๊ฐ ๋ณต์ก๋๊ฐ ๊ฐ์๋ vector๊ฐ ๊ฑฐ์ ํญ์ ๋น ๋ฅธ ์ด์ .
Q: list์ O(1) ์ค๊ฐ ์ฝ์ ์ด ์ ์ค์ ๋ก vector๋ณด๋ค ๋๋ฆฐ๊ฐ์?
1
2
3
4
5
6
7
8
์ธ ๊ฐ์ง ์ด์ :
1) ์์น iterator๋ฅผ ์์ ๋ค๊ณ ์์ด์ผ๋ง O(1) โ ์์ผ๋ฉด find๊ฐ O(n)
2) ์ ๋
ธ๋ ํ ๋น์ด operator new ํธ์ถ (์์ญ~์๋ฐฑ ns) + ์บ์ ๋ฏธ์ค
3) vector์ memmove๋ SIMD๋ก ํ ๋ฒ์ ์ฌ๋ฌ ๋ฐ์ดํธ ์ด๋, ๊ฒ๋ค๊ฐ
๋ฐ์ดํฐ๊ฐ ์บ์์ ์ด๋ฏธ ์ฌ๋ผ์ ์์ด ์ฌ์ค์ ๋ฌด๋ฃ
๊ฒฐ๋ก : N์ด ์๋ง~์์ญ๋ง ์ดํ๋ฉด vector ์์น,
๊ทธ ์ด์๋ ์บ์ ํจ์จ๋ก vector๊ฐ ์ด๊ธฐ๋ ๊ฒฝ์ฐ ๋๋ถ๋ถ.
Q: ์บ์ ๋ผ์ธ์ด ์ ํํ ๋ญ๊ฐ์?
1
2
3
4
5
6
7
CPU๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ฐ์ ธ์ฌ ๋ ํ ๋ฐ์ดํธ์ฉ ๊ฐ์ ธ์ค์ง ์๊ณ
์ผ์ ๋จ์๋ก ๊ฐ์ ธ์ค๋๋ฐ, ๊ทธ ๋จ์๊ฐ ์บ์ ๋ผ์ธ.
x86_64์์๋ ๋ณดํต 64๋ฐ์ดํธ.
ํ ๋ฒ ๊ฐ์ ธ์จ ๋ผ์ธ ์์ ๋ค๋ฅธ ๋ฐ์ดํฐ๋ ๊ฑฐ์ ๋ฌด๋ฃ(L1 ~1ns)๋ก ์ ๊ทผ.
vector๋ 64๋ฐ์ดํธ ์์ int 16๊ฐ๊ฐ ๋ค์ด์ ์ฒซ ๋ฏธ์ค ํ 15๊ฐ๋ ์บ์ ํํธ.
list๋ ๋
ธ๋๊ฐ ๋ถ์ฐ๋ผ ๋งค ๋
ธ๋๋ง๋ค ์ ๋ผ์ธ ๋ก๋ โ ์บ์ ๋ฏธ์ค ํญํ.
Q: ํ๋ฆฌํ์ฒ๊ฐ ๋ญ๊ฐ์?
1
2
3
4
5
6
7
8
9
CPU์ ๋ด์ฅ๋ ํ๋ก๋ก, ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ํจํด์ ๊ฐ์งํด
๋ค์์ ํ์ํ ์บ์ ๋ผ์ธ์ ๋ฏธ๋ฆฌ ๊ฐ์ ธ์ต๋๋ค.
vector ์ํ: ๋ผ์ธ N โ N+1 โ N+2 ... ์์ฐจ ํจํด ๊ฐ์ง โ
๋ค์ ๋ผ์ธ์ ๋ฏธ๋ฆฌ ๋ก๋ํด ๋ฉ๋ชจ๋ฆฌ ์ง์ฐ์ด ์ฌ์ค์ ์ฌ๋ผ์ง
list ์ํ: ๋
ธ๋ next ํฌ์ธํฐ๊ฐ ๋ฌด์์ ์ฃผ์ โ ํจํด ์์ โ
ํ๋ฆฌํ์ฒ ๋ฌด๋ ฅ โ DRAM 100ns ร N๋ฒ ๊ทธ๋๋ก ๋ถ๋ด
vector๊ฐ ๋น ๋ฅธ ์ด์ ์ ์ ๋ฐ์ ํ๋ฆฌํ์ฒ ๋๋ถ.
Q: amortized O(1)์ด ๋ญ๊ฐ์?
1
2
3
4
5
6
7
8
9
10
"ํ๊ท ์ ์ผ๋ก O(1)์ด์ง๋ง ๊ฐ๋ O(n) ๋น์ฉ์ด ๋๋" ์ฐ์ฐ.
vector::push_back์:
- ๋๋ถ๋ถ O(1) (capacity ์ฌ์ ์์ ๋)
- ๊ฐ๋ O(n) (์ฌํ ๋น ๋ฐ์ ์ ๋ชจ๋ ์์ ์ด๋)
์ฑ์ฅ ์ธ์๊ฐ 2๋ฐฐ๋ผ N๊ฐ push_back ๋์ ๋น์ฉ์ด O(2N) = O(N).
ํ ๋ฒ ํ๊ท ํ๋ฉด O(1) โ ๋ถํ ์ํ(amortized) ๋ถ์.
reserve๋ก ๋ฏธ๋ฆฌ capacity๋ฅผ ์ก์ผ๋ฉด ์ง์ง O(1) ๋ณด์ฅ.
Q: vector iterator๋ ์ธ์ ๋ฌดํจํ๋๋์?
1
2
3
4
5
6
7
8
9
10
11
์ฌํ ๋น ์ ๋ชจ๋ iterator/ํฌ์ธํฐ/์ฐธ์กฐ ๋ฌดํจํ:
push_back, emplace_back, insert (capacity ์ด๊ณผ ์)
reserve (n > capacity)
resize, shrink_to_fit
๋ถ๋ถ ๋ฌดํจํ:
insert/erase (์ฌํ ๋น ์์ ๋) โ ํด๋น ์์น ์ดํ ๋ฌดํจ
clear โ ๋ชจ๋
list๋ ์ญ์ ๋ ๋
ธ๋๋ง ๋ฌดํจํ๋ผ splice/merge ๊ฐ์ ์ฐ์ฐ์ด ์์ .
์ด๊ฒ list์ ๊ฐ์ฅ ์ ์งํ ๊ฐ์ .
**Q: vector
1
2
3
4
5
6
7
8
9
10
11
์ฌํ ๋น ์ vector๋ ๊ธฐ์กด ์์๋ฅผ ์ ๋ฒํผ๋ก ์ฎ๊ฒจ์ผ ํจ.
T๊ฐ noexcept move๋ฅผ ๊ฐ์ง๋ฉด:
โ vector๊ฐ move ์ฌ์ฉ โ ๋น ๋ฅด๊ณ strong exception guarantee
T์ move๊ฐ throw ๊ฐ๋ฅํ๋ฉด:
โ vector๊ฐ ์์ ์ ์ํด copy ์ฌ์ฉ โ ๋๋ฆผ
T์ copy๋ throwํ๋ฉด:
โ basic guarantee๋ก ๊ฐ๋ฑ
๋ฐ๋ผ์ ์ฌ์ฉ์ ์ ์ ํด๋์ค๋ ํญ์ noexcept move๋ฅผ ์ ์ํ๋ ๊ฒ ์ข์.
์ด๊ฒ 12๋ฒ Rule of Five์ ๊ฐ์ฅ ์ค์ํ ์์ฉ ์ฌ๋ก.
Q: list๊ฐ ์ ๋ง ํ์ํ ๊ฒฝ์ฐ๋ ์ธ์ ์ธ๊ฐ์?
1
2
3
4
5
6
7
8
9
10
11
12
13
๊ทนํ ๋๋ฌธ ์ผ์ด์ค (5์กฐ๊ฑด ๋ชจ๋ ๋ง์กฑ):
1) ๋งค์ฐ ํฐ ๊ฐ์ฒด (์ KB ์ด์)
2) ์ฆ์ splice/merge
3) iterator/ํฌ์ธํฐ ์์ ์ฑ์ด ํ์
4) ๊ฒ์์ ๊ฑฐ์ ์ ํจ
5) ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ ์ ๊ฒฝ ์ ์
ํ๋๋ผ๋ ๋น ์ง๋ฉด ๋ณดํต ๋ค๋ฅธ ์๋ฃ๊ตฌ์กฐ๊ฐ ๋ ๋์:
- ์บ์๋ ์ ๊ฒฝ X but ์์ ์ฑ ํ์ โ vector<unique_ptr<T>>
- ์์ชฝ push ํ์ โ std::deque
- ๋จ๋ฐฉํฅ + ๋ฉ๋ชจ๋ฆฌ ์ ์ฝ โ std::forward_list
Stroustrup: "์์ฌ์ค๋ฌ์ฐ๋ฉด vector. ๊ทธ๋๋ ์์ฌ์ค๋ฌ์ฐ๋ฉด ๊ทธ๋๋ vector."
Q: deque์ list์ ์ฐจ์ด๋?
1
2
3
4
5
6
7
8
9
10
11
12
13
deque (Double-Ended Queue):
- ์ฒญํฌ ๊ธฐ๋ฐ (๋ณดํต 4KB ์ฒญํฌ ์ฌ๋ฌ ๊ฐ๋ฅผ ์ธ๋ฑ์ค ๋ฐฐ์ด๋ก ๊ด๋ฆฌ)
- push_front O(1), push_back O(1), ์์ ์ ๊ทผ O(1)
- ์ฒญํฌ ์์์ ์ฐ์ ๋ฉ๋ชจ๋ฆฌ โ ์บ์ ์นํ (vector๋ณด๋ค ์ฝ๊ฐ ๋ชปํจ)
- iterator๋ front/back push ์ ์์ (vector์ ๋ค๋ฅธ ์ )
list:
- ๋
ธ๋๋ณ ๋ถ์ฐ ํ ๋น
- ์์ ์ ๊ทผ O(n)
- ์บ์ ์ ๋
deque๋ "vector + ์์ชฝ push"์ด๊ณ , list๋ "iterator ์์ ์ฑ + ๋
ธ๋ splice"
๋๋ถ๋ถ ์ฌ์ฉ ์ฌ๋ก์์ deque > list.
Q: TArray์ std::vector์ ์ฐจ์ด๋?
1
2
3
4
5
6
7
8
9
10
๊ฑฐ์ ๊ฐ์ โ ๋ ๋ค ์ฐ์ ๋ฉ๋ชจ๋ฆฌ ๋์ ๋ฐฐ์ด, ์ฑ์ฅ ์ธ์ 1.5x~2x.
์ธ๋ฆฌ์ผ ์ถ๊ฐ ๊ธฐ๋ฅ:
- UPROPERTY()๋ก GC ํตํฉ โ TArray<UItem*> ์์ UObject๋ GC๊ฐ ์ถ์
- ๋ธ๋ฃจํ๋ฆฐํธยท๋ํ
์ผ ํจ๋ยทreplication ์๋ ์ง์
- RemoveAtSwap โ ์์ ๋ฌด์ํ๊ณ O(1) ์ญ์ (๋ง์ง๋ง ์์์ swap)
- GetAllocator๋ก ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ ์ปค์คํฐ๋ง์ด์ง
- ์ธ๋ฆฌ์ผ ๋ฉ๋ชจ๋ฆฌ ์์คํ
(FMemory) ํตํฉ
UObject ํฌ์ธํฐ ์ปจํ
์ด๋๋ std::vector๊ฐ ์๋๋ผ ๋ฐ๋์ TArray + UPROPERTY.
Q: ์ธ๋ฆฌ์ผ์ ์ list ๋์์ ์ ๋๋์?
1
2
3
4
5
6
7
8
9
10
11
๊ฒ์ ์์ง์ ๋งค ํ๋ ์ ์๋ง~์์ญ๋ง ๊ฐ ๊ฐ์ฒด๋ฅผ ์ํ.
์บ์ ๋ฏธ์ค 100ns ร ๋ง ๊ฐ = 1ms์ฉ ์๋ ์
โ 60FPS(16.6ms) ์์ฐ ์๋ฐ.
๋ฐ๋ผ์ ์ธ๋ฆฌ์ผ์:
- TArray (vector ๋์) 1๊ธ ์๋ฏผ
- TMapยทTSet (ํด์ ์ปจํ
์ด๋) 1๊ธ ์๋ฏผ
- TLinkedListยทTDoubleLinkedList โ 1๊ธ์ด ์๋ ํฌํผ ์์ค
- ํธ๋ฆฌยทBST ์ปจํ
์ด๋ ๊ฑฐ์ ์์ (์บ์ ์ ๋์ )
ECSยทSoA ํจํด(Entity Component System)๋ ๊ฐ์ ์บ์ ์ฒ ํ.
"์บ์ ์นํ โ ๊ฒ์ ์ฑ๋ฅ"์ด ์์ง ์ค๊ณ ์ ๋ฐ์ ๊น๋ฆฐ ์์น.
10. ๋ชจ์๋ฉด์ ๋ต๋ณ ํ ํ๋ฆฟ (1๋ถ / 3๋ถ)
10-1. 1๋ถ ๋ฒ์ โ ํต์ฌ๋ง
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
vector์ list๋ ๋ ๋ค ์ํ์ค ์ปจํ
์ด๋์ง๋ง ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์์ด ์ ๋ฐ๋์
๋๋ค.
vector๋ ์ฐ์ ๋ฉ๋ชจ๋ฆฌ ๋์ ๋ฐฐ์ด์ด๊ณ , list๋ ๋
ธ๋๊ฐ ํ์ ๋ถ์ฐ๋ ์ด์ค ์ฐ๊ฒฐ
๋ฆฌ์คํธ์
๋๋ค. ์๊ฐ ๋ณต์ก๋๋ง ๋ณด๋ฉด list๊ฐ ์ค๊ฐ ์ฝ์
O(1)๋ก ์ ๋ฆฌํด ๋ณด์ด์ง๋ง,
์ค์ธก ์ฑ๋ฅ์ ๊ฑฐ์ ๋ชจ๋ ์ํฌ๋ก๋์์ vector๊ฐ ์์นํฉ๋๋ค.
์ด์ ๋ CPU ์บ์์
๋๋ค. CPU๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ 64๋ฐ์ดํธ ์บ์ ๋ผ์ธ ๋จ์๋ก ๊ฐ์ ธ์ค๋๋ฐ,
vector๋ ํ ๋ผ์ธ์ ์์๊ฐ ์ฌ๋ฌ ๊ฐ ๋ค์ด์ค๊ณ ํ๋ฆฌํ์ฒ๊ฐ ๋ค์ ๋ผ์ธ์ ๋ฏธ๋ฆฌ
๋ก๋ํฉ๋๋ค. list๋ ๋
ธ๋๊ฐ ๋ถ์ฐ๋ผ ๋งค ๋
ธ๋๋ง๋ค ์บ์ ๋ฏธ์ค๊ฐ ๋์, 1M๊ฐ ์ํ
๋ฒค์น๋งํฌ์์ vector ~1ms, list ~100ms โ 100๋ฐฐ ์ฐจ์ด๊ฐ ๋ฉ๋๋ค.
๋ฐ๋ผ์ ํ๋ ํ๋์จ์ด์์๋ ๊ฑฐ์ ํญ์ vector๊ฐ ์ ๋ต์ด๊ณ , list๋ "๋งค์ฐ ํฐ
๊ฐ์ฒด + ์ฆ์ splice + iterator ์์ ์ฑ ํ์"๋ผ๋ ์ข์ ๊ฒฝ์ฐ์๋ง ์ ๋นํ๋ฉ๋๋ค.
์์ฌ์ค๋ฌ์ฐ๋ฉด vector๋ฅผ ์ฐ๊ณ , ๊ทธ๋๋ ์์ฌ์ค๋ฌ์ฐ๋ฉด ๊ทธ๋๋ vector๋ฅผ ์ฐ๋ผ๋ ๊ฒ
Stroustrup์ด ์ง์ ๊ถ๊ณ ํ๋ ๋ฃฐ์
๋๋ค.
10-2. 3๋ถ ๋ฒ์ โ ์บ์ยทiteratorยท์ธ๋ฆฌ์ผ๊น์ง
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
[1] ๋ฉ๋ชจ๋ฆฌ ๋ ์ด์์๋ถํฐ ์ ๋ฐ๋์
๋๋ค.
vector๋ ์ฐ์ ๋ฉ๋ชจ๋ฆฌ ๋์ ๋ฐฐ์ด์
๋๋ค. capacity๊ฐ ๋ถ์กฑํ๋ฉด ๋ณดํต 1.5๋ฐฐ(MSVC)
๋ 2๋ฐฐ(libstdc++)๋ก ์ฌํ ๋นํ๋ฉด์ ๋ชจ๋ ์์๋ฅผ ์ ๋ฒํผ๋ก ์ฎ๊น๋๋ค. ๊ทธ๋์
push_back์ amortized O(1) โ ํ๊ท ์ O(1)์ด์ง๋ง ๊ฐ๋ O(n) ๋น์ฉ์ด ๋ฐ์ํฉ๋๋ค.
๋ฏธ๋ฆฌ reserve๋ก capacity๋ฅผ ์ก์ผ๋ฉด ์ฌํ ๋น ์์ด ์ง์ง O(1)์ด ๋ฉ๋๋ค.
list๋ ์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ก, ๊ฐ ๋
ธ๋๊ฐ ํ์ ๋ฐ๋ก ํ ๋น๋๊ณ prevยทnext ํฌ์ธํฐ๋ก
์ฐ๊ฒฐ๋ฉ๋๋ค. ๋
ธ๋ ํ๋์ prev 8B + next 8B + ๋ฐ์ดํฐ + ํ ํค๋ ์ฝ 16B โ
int 4๋ฐ์ดํธ๋ฅผ ์ํด 40๋ฐ์ดํธ ๋
ธ๋๋ฅผ ๋ง๋๋ ์
์
๋๋ค. 1M๊ฐ int๋ฅผ ๋ด์ผ๋ฉด
vector๋ 4MB, list๋ 40MB ์ ๋ โ ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ด 10๋ฐฐ ์ฐจ์ด ๋ฉ๋๋ค.
[2] ์๊ฐ ๋ณต์ก๋๋ ํจ์ ์ด ์์ต๋๋ค.
์ด๋ก ์ list๊ฐ ์ค๊ฐ ์ฝ์
O(1)๋ก ์ ๋ฆฌํฉ๋๋ค. ํ์ง๋ง ๊ทธ O(1)์ ์์น iterator๋ฅผ
์ด๋ฏธ ์์ ๋ค๊ณ ์์ ๋ ์๊ธฐ๊ณ , ์ค์ ๋ก๋ ๊ฐ์ find๋ก ์ฐพ์์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ
๋๋ถ๋ถ์ด๋ผ ๊ฒฐ๊ตญ O(n)์
๋๋ค. ๊ฒ๋ค๊ฐ ์ ๋
ธ๋ ํ ๋น์ operator new ํธ์ถ๊ณผ
์บ์ ๋ฏธ์ค๊ฐ ๋ฐ๋ผ์ต๋๋ค.
vector์ ์ค๊ฐ ์ฝ์
์ ์ด๋ก ์ O(n)์ด์ง๋ง memmove๊ฐ SIMD๋ก ํ ๋ฒ์ ์ฌ๋ฌ
๋ฐ์ดํธ์ฉ ์ฎ๊ธฐ๊ณ , ๋ฐ์ดํฐ๊ฐ ์ด๋ฏธ ์บ์์ ์์ด ๊ฑฐ์ ๋ฌด๋ฃ์
๋๋ค. Stroustrup์
์ ๋ช
ํ ๊ฐ์ฐ์์ N๊ฐ ๋ฌด์์ ์์น ์ฝ์
๋ฒค์น๋งํฌ๋ฅผ ๋ณด๋ฉด, N์ด 50๋ง์ผ ๋
vector๋ 1.1์ด, list๋ 35์ด โ 30๋ฐฐ ์ฐจ์ด๋ก vector๊ฐ ์ด๊น๋๋ค.
[3] ํต์ฌ์ CPU ์บ์์
๋๋ค.
ํ๋ CPU๋ ๋ฉ๋ชจ๋ฆฌ๋ณด๋ค 100๋ฐฐ ๋น ๋ฅด๊ณ , ๊ทธ ๊ฒฉ์ฐจ๋ฅผ ์บ์๋ก ๋ฉ์๋๋ค. L1์ ์ฝ
1ns, L2๋ 3ns, L3๋ 12ns, DRAM์ 100ns๋ก 4๋จ๊ณ์
๋๋ค. CPU๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ
ํ ๋ฐ์ดํธ์ฉ์ด ์๋๋ผ 64๋ฐ์ดํธ ์บ์ ๋ผ์ธ ๋จ์๋ก ๊ฐ์ ธ์ต๋๋ค. ๊ทธ๋์ ํ
๋ผ์ธ์ ๊ฐ์ ธ์ค๋ฉด ๊ทธ ์์ ๋ค๋ฅธ ๋ฐ์ดํฐ๋ ๊ฑฐ์ ๊ณต์ง์
๋๋ค.
vector๋ ์ฐ์ ๋ฉ๋ชจ๋ฆฌ๋ผ ํ ๋ผ์ธ์ int๊ฐ 16๊ฐ ๋ค์ด์ค๊ณ , ํ๋์จ์ด ํ๋ฆฌํ์ฒ๊ฐ
์์ฐจ ํจํด์ ๊ฐ์งํด ๋ค์ ๋ผ์ธ์ ๋ฏธ๋ฆฌ ๊ฐ์ ธ์ต๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ์ง์ฐ์ด
์ฌ์ค์ ์ฌ๋ผ์ง๋๋ค. list๋ ๋
ธ๋๊ฐ ๋ฌด์์ ์ฃผ์์ ๋ถ์ฐ๋ผ ๋งค ๋
ธ๋๋ง๋ค ์
๋ผ์ธ์ ๊ฐ์ ธ์์ผ ํ๊ณ ํ๋ฆฌํ์ฒ๋ ๋ฌด๋ ฅํฉ๋๋ค. ๊ทธ๋์ 1M ์ํ ์ ์บ์
๋ฏธ์ค๊ฐ ์ฝ 1M๋ฒ ์ผ์ด๋ 100ms๋ฅผ ๊ทธ๋๋ก ๋ถ๋ดํฉ๋๋ค.
์ด๋ก ๋ณต์ก๋๊ฐ ๊ฐ์๋ ์บ์ ์นํ์ฑ์ด ์ค์ธก ์ฑ๋ฅ์ ๊ฒฐ์ ํ๋ค โ ์ด๊ฒ 13๋ฒ
์ฃผ์ ์ ํต์ฌ ๋ฉ์์ง์
๋๋ค.
[4] iterator ๋ฌดํจํ๋ ๋ค๋ฆ
๋๋ค.
vector๋ ์ฌํ ๋น ์ ๋ชจ๋ iteratorยทํฌ์ธํฐยท์ฐธ์กฐ๊ฐ ๋ฌดํจํ๋ฉ๋๋ค. ์ค๊ฐ
insert/erase๋ ๊ทธ ์์น ์ดํ๊ฐ ๋ฌดํจํ๋ฉ๋๋ค. list๋ ์ญ์ ๋ ๋
ธ๋ ์์ ๋ง
๋ฌดํจํ๋๊ณ ๋ค๋ฅธ ๋
ธ๋๋ ์์ ํด spliceยทmerge ๊ฐ์ ๋
ธ๋ ์ฌ๋ฐฐ์น๊ฐ ๊น๋ํฉ๋๋ค.
์ด๊ฒ list์ ๊ฑฐ์ ์ ์ผํ ์ ์งํ ๊ฐ์ ์
๋๋ค.
์์ธ ์์ ์ฑ ๋ฉด์์๋ list๋ push ์ฐ์ฐ์ด ์๋์ผ๋ก strong guarantee์ด๊ณ ,
vector๋ noexcept ์ด๋ ์์ฑ์๊ฐ ์์ด์ผ ํจ์จ์ ์ธ strong guarantee๋ฅผ
์ ๊ณตํฉ๋๋ค. ๊ทธ๋์ ์ฌ์ฉ์ ์ ์ ํด๋์ค๋ ํญ์ noexcept move๋ฅผ ์ ์ํ๋
๊ฒ ์ข์ต๋๋ค โ Rule of Five์์ ๋ค๋ฃฌ ๊ทธ ์ง์ ์
๋๋ค.
[5] ๊ฒฐ๋ก ๊ณผ ์ธ๋ฆฌ์ผ.
ํ๋ ํ๋์จ์ด์์ list๋ ๊ฑฐ์ ํญ์ ์๋ชป๋ ์ ํ์
๋๋ค. ๋งค์ฐ ํฐ ๊ฐ์ฒด์
์ฆ์ splice๊ฐ ํ์ํ๊ณ iterator ์์ ์ฑ์ด ํ์์ธ ์ข์ ๊ฒฝ์ฐ์๋ง ์ ๋นํ๋๊ณ ,
๊ทธ๋ง์ ๋ ๋ณดํต vector<unique_ptr<T>>๋ std::deque๋ก ๋ ์ ํ๋ฆฝ๋๋ค.
Stroustrup, Sutter, Sean Parent ๋ชจ๋ "์์ฌ์ค๋ฌ์ฐ๋ฉด vector"๋ฅผ ๊ถํฉ๋๋ค.
์ธ๋ฆฌ์ผ์ ์ด ์ฒ ํ์ ๋ ๊ฐํ๊ฒ ์ ์ฉํฉ๋๋ค. TArray๊ฐ vector ๋์ 1๊ธ ์๋ฏผ
์ด๊ณ , std::list ๋์ ์๋ฃ๊ตฌ์กฐ๋ ์๋์ ์ผ๋ก 1๊ธ์ผ๋ก ๋์ง ์์์ต๋๋ค.
TLinkedListยทTDoubleLinkedList๊ฐ ์์ง๋ง ํฌํผ ์์ค์
๋๋ค. ๊ฒ์ ์์ง์ ๋งค
ํ๋ ์ ์๋ง ๊ฐ์ฒด๋ฅผ ์ํํด์ผ ํด์ ์บ์ ์นํ์ฑ์ด ๊ณง ํ๋ ์ ์์ฐ์ด๊ธฐ
๋๋ฌธ์
๋๋ค. ECSยทSoA ํจํด๋ ๊ฐ์ ์ด์ ๋ก ์ฑํ๋ฉ๋๋ค.
์์ฝํ๋ฉด, vector๋ฅผ ๊ธฐ๋ณธ์ผ๋ก ์ฐ๊ณ , ์ธก์ ํด์ vector๊ฐ ๋๋ฆผ์ ์ฆ๋ช
ํ ํ์์ผ
๋ค๋ฅธ ์ปจํ
์ด๋๋ฅผ ๊ฒํ ํ๋ค โ ์ด๊ฒ 13๋ฒ์ ๊ฐ์ฅ ์ค์ํ ํ ์ค์
๋๋ค.
์ฐธ๊ณ
- 11_smart_pointer.md โ
unique_ptr/shared_ptr์ด ์ปจํ ์ด๋ ์์์ผ ๋์ ํจํด (vector<unique_ptr<T>>์ด list ๋์์ธ ์ด์ ) - 12_prevent_copy.md โ Rule of Five์ noexcept ์ด๋, move-only ํ์
(
unique_ptr,thread,ifstream)์ ์ปจํ ์ด๋์ ๋ด๊ธฐ - 09_rtti_raii.md โ RAII ์์ ๊ด๋ฆฌ, vector ์์ฒด๊ฐ RAII ์ ์ ์ฌ๋ก
- 10_pointer_deepdive.md โ vector ์ฌํ ๋น ํ ๋๊ธ๋ง ํฌ์ธํฐ (์บ์ ์นํ vs ์์ ์ฑ ํธ๋ ์ด๋์คํ์ ์ ํํ ์ฌ๋ก)
- 00_index.md โ CS ๋ฉด์ ์ธ๋ฑ์ค (์ด๋ฒ 13๋ฒ์ด STL+์์คํ ์์ญ ์ง์ ์ )