[TOC]

순차 컨테이너

순차 컨테이너는 윈소들을 선형적인 순차열(Linear Sequence)로 저장.
원소들을 정렬하지 않고, 저장한 순서대로 배열된다.

  • array<T, N> 컨테이너

    • T타입, 고정길이 N으로 된 순차열
  • vector

    • T 타입, 가변길이 순차열을 정의하며. 필요할때 자동으로 크기가 늘어난다.
  • deque

    • T 타입, 자동으로 길이가 늘어나는 가변길이 순차열, 양쪽 끝에서 원소를 추가하거나 삭제할수 있음.
  • list

    • 이중 연결 리스트로 된 가변길이 순차열, 모든 위치에서 원소를 추가하거나 삭제할수 있음.
      만약 특정 원소에 접근한다면 첫번째 원소에서 리스트를 따라 움직여야되기 때문에, array, vector, deque보다 느리다.
  • forward_list

    • 단일 연결 리스트로 연결된 T 객체의 가변길이 순차열 정의
      리스트 컨테이너보다 빠르고 더 적은 메모리르 사요하지만, 항상 첫번재부터 접근을 시작해야됨

array <T, N> 컨테이너

표준배열에 해당하는 컨테이너 타입.

장점

  1. at()을 사용해 원소를 접근하면 범위를 벗어난 인덱스에 접근하는지 탐지가가능
  2. 컨테이너에 몇개의 원소가 있는지 알고 있으니, 함수에 원소의 갯수를 별도로 지정하지않아도 인수로 전달하기가 좋다.

원소에 접근하기

일반배열처럼 배열첨자를 사용할수있다.

1
value.at(4) = value.at(3) + 2.0 * value.at(1);

at에 사용한 인수가 범위를 벗어난 인덱스인지 확인하고, 범위를 벗어났다면 out of range 예외가 발생한다.
operator에 경계 검사를 하지않는 이유는, 성능때문이다. 원소 접근할때마다 인덱스를 검증한다면
오버헤드가 발생하기 때문이다.

1
2
3
4
5
6
7
8
9
10
11
// 원소들의 합계
double total {};
for(size_t i {}; i < values.size(); ++i)
total += values[i];

// 컨테이너 비어있는지 확인
values.empty(); // -> return bool

// 범위기반 for
for(auto&& value : values)
total += value;

Example

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
#include <iostream>
#include <iomanip>
#include <array>

int main()
{
const unsigned int min_wt{ 100U };
const unsigned int max_wt{ 250U };
const unsigned int wt_step{ 10U };
const size_t wt_count{ 1 + (max_wt - min_wt) / wt_step };

const unsigned int min_ht{ 48U };
const unsigned int max_ht{ 84U };
const unsigned int ht_step{ 2U };
const size_t ht_count{ 1 + (max_ht - min_ht) / ht_step };


const double lbs_per_kg{ 2.20462 };
const double ins_per_m{ 39.3701 };

std::array<unsigned int, wt_count> weight_lbs;
std::array<unsigned int, wt_count> height_lns;

for (size_t i{}, w{ min_wt }; i < wt_count; w += wt_step, ++i)
weight_lbs.at(i) = w;

unsigned int h{ min_ht };
for (auto& height : height_lns)
{
height = h;
h += ht_step;
}

std::cout << std::setw(7) << " |";
for (const auto& w : weight_lbs)
std::cout << std::setw(7) << w << " |";
std::cout << std::endl;

for (size_t i{ 1 }; i < wt_count; ++i)
std::cout << "------------\n";

double bmi{};
unsigned int feet{};
unsigned int inches{};
const unsigned int inches_per_foot{ 12U };

for (const auto& h : height_lns)
{
feet = h / inches_per_foot;
inches = h % inches_per_foot;
std::cout << std::setw(7) << feet << "'" << std::setw(2) << inches << "\"" << "|";
std::cout << std::fixed << std::setprecision(1);

for (const auto & w : weight_lbs)
{
bmi = h / ins_per_m;
bmi = (w / lbs_per_kg) / (bmi * bmi);
std::cout << std::setw(2) << " " << bmi << " |";
}

std::cout << std::endl;
}

for (size_t i{ 1 }; i < wt_count; ++i)
std::cout << "------------\n";
}

Array Container Iterator 사용

array에는 begin(), end()가 정의되어 있음.
실제 이터레이터 타입은 std::array<T, N>::iterator가 실제타입
std::generate() 함수 템플릿을 이용하면, 함수 객체가 계산한 값으로 범위를 초기활수도 있음.

1
2
3
4
unsigned int height {};
std::generate(std::begin(height_ins), std::end(height_ins),
[height, &min_ht, &ht_step] () mutable
{return height += height == 0 ? min_ht : ht_step });

array 컨테이너를 연속값으로 초기화하고싶을때는 numeric 헤더에 있는 iota

1
2
std::array<double , 10> values;
std::iota(std::begin(values), std::end(values), 10.0); // 원소들의 값을 10.0부터 19.0 까지 설정한다.

operator++() 을 지원하는 타입이라면 iota 함수를 쓸수있다.

위의 generate, iota는 알고리즘인데, 순방향 반복자만 있다면 사용가능하다. 즉 다른 컨테이너에서도 사용가능.

const iterator를 반환하는 cbegin, cend가 있다.
원소에 접근은 하지만 수정은 하지않을때 const 반복자를 사용한다.

1
2
3
4
5
6
std::array<double, 5> these {....};
double sum {};
auto start = rbegin(these);
auto finish = rend(these);
while(start != finish)
sum += *(start++);

Array Conatiner 비교

두 Array 컨테이너의 크기가 같고 원소가 같고, 이 타입이 비교연산을 지원한다면 비교연산자를 사용할수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
array<double, 4> these { ... };
array<double, 4> those { ... };

if(these == those)
// 모든 원소가 일치해야된다.

if(these != those)
// 대응되지않은 원소가 하나이상 있다면

if(these < those)
// 같이 순회하면서 만약 these[i] < those[i] 를 만족하는 해가 나온다면 true다

if(these > those)