도순씨의 코딩일지

STL :: 시퀸스 컨테이너(1) 본문

𝐏𝐑𝐎𝐆𝐑𝐀𝐌𝐌𝐈𝐍𝐆/𝐂++

STL :: 시퀸스 컨테이너(1)

도순씨 2020. 9. 12. 00:00

🌼 vector

vector는 시퀸스 컨테이너이므로 원소의 저장 위치(순서)가 정해지며 배열 기반컨테이너입니다.

vector은 큐와 비슷하게 앞쪽이 막혀있는 형태로 앞쪽에는 원소를 추가 및 제거할 수 없습니다. 오직 뒤쪽에서 원소의 변경이 가능합니다.

 

 

⭐️ vector의 push_back()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <vector>
using namespace std;
 
int main(void){
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);
 
    for(int i = 0 ; i < v.size() ; ++i)
        cout << v[i] << endl;
    return 0;
}
cs

 

⭐️ vector의 push_back() 실행결과

1
2
3
4
5
10
20
30
40
50
cs

 

이번에는 vector의 typedef된 멤버 형식 size_type을 사용한 예제입니다.

 

⭐️ vector의 size_type 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
#include <vector>
using namespace std;
 
int main(void){
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);
 
    for(vector<int> :: size_type i = 0 ; i < v.size() ; ++i)
        cout << v[i] << endl;
    cout << typeid(vector<int> :: size_type).name() << endl;
    return 0;
}
cs

 

⭐️ vector의 size_type 실행결과

1
2
3
4
5
6
10
20
30
40
50
m
cs

 

여기서 두 가지 코드를 살펴보도록 합시다.

💡 vector<int> :: size_type : vector의 크기, 첨자 형식을 위한 typedef 멤버 형식

💡 typeid( T ) : T에 대한 typeinfo 객체를 리턴

 

다음은 vector의 크기를 반환하는 함수예제입니다.

 

⭐️ vector의 size(), capacity(), max_size()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <vector>
using namespace std;
 
int main(void){
    vector<int> v;
 
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);
 
    for(vector<int> :: size_type i = 0 ; i < v.size() ; ++i)
        cout << v[i] << endl;
    cout << endl;
    
    cout << v.size() << endl;
    cout << v.capacity() << endl;
    cout << v.max_size() << endl;
 
    return 0;
}
cs

 

⭐️ vector의 size(), capacity(), max_size() 실행결과 

1
2
3
4
5
6
7
8
9
10
20
30
40
50
 
5
8
4611686018427387903
cs

 

capacity는 유일하게 vector만이 가지는 멤버 함수입니다. vector는 원소를 컨테이너에 계속 추가할 수 있습니다. 원소를 추가할 때 마다 메모리 크기를 늘려주기 위해서 메모리를 재할당해야 합니다. 하지만 원소가 삽입될 때마다 메모리를 재할당하는 것은 매우 비효율적입니다. 따라서 넉넉하게 메모리를 할당하고 그 뒤에 데이터를 삽입하는 것입니다. 저는 CLion을 사용하여 capacity의 값이 8이 나왔지만, 컴파일러마다 값이 다를 수도 있습니다.

 

reserve()를 이용하여 메모리의 사용을 예약할 수도 있습니다. 또는 생성자를 이용하여 미리 사이즈를 할당받을 수도 있습니다. 

 

다음 예제는 clear()로 모든 원소를 제거하고 empty()로 컨테이너가 비었는지 검사하는 예제입니다.

 

⭐️ vector의 clean()과 empty

 

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
#include <iostream>
#include <vector>
using namespace std;
 
int main(void){
    vector<int> v(5);
 
    v[0= 10;
    v[1= 20;
    v[2= 30;
    v[3= 40;
    v[4= 50;
    for(vector<int> :: size_type i = 0 ; i < v.size() ; ++i)
        cout << v[i] << " ";
    cout << endl;
    cout << "size: " << v.size() << " capacity: " << v.capacity() << endl;
 
    v.clear();
    cout << "size: " << v.size() << " capacity: " << v.capacity() << endl;
 
    if(v.empty()){
        cout << "v에 원소가 없습니다." << endl;
    }
 
    return 0;
}
cs

 

⭐️ vector의 clean()과 empty 실행결과

1
2
3
4
5
10 20 30 40 50 
size: 5 capacity: 5
size: 0 capacity: 5
v에 원소가 없습니다.
 
cs

 

모든 컨테이너는 컨테이너 객체끼리 교환할 수 있는 swap() 멤버 함수를 제공합니다.

 

⭐️ swap을 사용한 할당 메모리 제거

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <vector>
using namespace std;
 
int main(void){
    vector<int> v(5);
 
    cout << "size: " << v.size() << " capacity: " << v.capacity() << endl;
 
    vector<int>().swap(v);  // 기본 생성자로 만든 vector 컨테이너와 v 컨테이너를 swap 한다.
    cout << "size: " << v.size() << " capacity: " << v.capacity() << endl;
 
    return 0;
}
cs

 

⭐️ swap을 사용한 할당 메모리 제거 실행결과

1
2
size5 capacity: 5
size0 capacity: 0
cs

 

다음 예제는 front(), back(), 참조를 이용해 원소를 수정해보겠습니다.

⭐️ vector의 from()와 back() 참조

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <vector>
using namespace std;
 
int main(){
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);
 
    for(vector<int> :: size_type i = 0 ; i < v.size() ; ++i)
        cout << v[i] << " ";
    cout << endl;
 
    v.front() = 100;
    v.back() = 500;
    for(vector<int> :: size_type i = 0 ; i < v.size() ; ++i)
        cout << v[i] << " ";
    cout << endl;
 
    return 0;
}
cs

 

⭐️ vector의 from()와 back() 참조 실행결과

1
2
10 20 30 40 50 
100 20 30 40 500 
cs

 

배열 기반 컨테이너인 vector와 deque는 일반배열처럼 임의 위치의 원소를 참조하는 두 인터페이스를 제공합니다. [] 연산자와 at()  멤버 함수가 그것입니다. [] 연산자는 범위 점검을 하지 않아 속도가 빠르고 at() 멤버 함수는 범위 점검을 하여 속도는 느리지만 안전하다는 장점이 있습니다.

 

⭐️ vector의 [] 연산자와 at() 멤버 함수

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
#include <iostream>
#include <vector>
using namespace std;
 
int main(){
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);
 
    for(vector<int> :: size_type i = 0 ; i < v.size() ; ++i)
        cout << v[i] << " ";
    cout << endl;
 
    v[0= 100;
    v[4= 500;
    for(vector<int> :: size_type i = 0 ; i < v.size() ; ++i)
        cout << v.at(i) << " ";
    cout << endl;
 
    v.at(0= 1000;
    v.at(4= 5000;
    for(vector<int> :: size_type i = 0 ; i < v.size() ; ++i)
        cout << v.at(i) << " ";
    cout << endl
 
    return 0;
}
cs

 

⭐️ vector의 [] 연산자와 at() 멤버 함수 실행결과

1
2
3
10 20 30 40 50 
100 20 30 40 500 
1000 20 30 40 5000 
cs

 

assign() 함수는 일괄적으로 값을 할당하는 데 사용합니다.

 

⭐️ vector의 assign()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <vector>
using namespace std;
 
int main(void){
    vector<int> v(51);
 
    for(vector<int> :: size_type i = 0 ; i < v.size() ; ++i)
        cout << v[i] << " ";
    cout << endl;
 
    v.assign(52);
 
    for(vector<int> :: size_type i = 0 ; i < v.size() ; ++i)
        cout << v[i] << " ";
    cout << endl;
 
    return 0;
}
cs

 

⭐️ vector의 assign() 실행결과

1
2
1 1 1 1 1 
2 2 2 2 2 
cs

 

다음 예제는 begin(), end() 멤버 함수를 이용하여 반복자를 사용하여 원소를 출력합니다.

 

⭐️ vector의 begin()과 end()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <vector>
 
using namespace std;
 
int main(){
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);
 
    for(vector<int> :: size_type i = 0 ; i < v.size() ; ++i)
        cout << v[i] << " ";
    cout << endl;
 
    for(vector<int> :: iterator iter = v.begin() ; iter != v.end() ; ++ iter)
        cout << *iter << " ";
    cout << endl;
    return 0;
}
cs

 

⭐️ vector의 begin()과 end() 실행결과

1
2
10 20 30 40 50 
10 20 30 40 50 
cs

 

배열 기반 컨테이너인 vector, deque는 임의 접근 반복자를 제공하고 이 임의 접근 반복자를 이용하여 +, -, +=, -=, [] 연산이 가능합니다.

 

⭐️ 일반 반복자와 상수 반복자

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
#include <iostream>
#include <vector>
using namespace std;
 
int main(){
    vector<int> v;
 
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);
 
    vector<int> :: iterator iter = v.begin();
    vector<int> :: const_iterator citer = v.begin();
 
    cout << *iter << endl;
    cout << *citer << endl;
 
    cout << *++iter << endl;
    cout << *++citer << endl;
    *iter = 100;
 
    return 0;
}
cs

 

⭐️ 일반 반복자와 상수 반복자 실행결과

1
2
3
4
10
10
20
20
cs

citer은 상수 반복자이므로 값의 변경이 불가능합니다.

 

다음으로 iterator와 reverse_iterator를 이용하여 컨테이너의 모든 원소를 출력하는 예제입니다.

 

⭐️ iterator와 reverse_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
#include <iostream>
#include <vector>
using namespace std;
 
int main(){
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);
 
    vector<int> :: iterator iter;
    vector<int> :: reverse_iterator riter;
 
    for(iter = v.begin() ; iter != v.end() ; ++iter)
        cout << *iter << " ";
    cout << endl;
 
    for(riter = v.rbegin() ; riter != v.rend() ; ++ riter)
        cout << *riter << " ";
    cout << endl;
    return 0;
}
cs

 

⭐️ iterator와 reverse_iterator 실행결과

1
2
10 20 30 40 50 
50 40 30 20 10 
cs

 

다음으로 insert() 함수와 erase() 함수를 알아봅시다. insert() 함수를 사용하면 원하는 위치에 값을 삽입할 수 있습니다. erase() 함수는 반복자가 가리키는 위치의 원소를 제거할 수 있습니다.

 

⭐️ insert() 멤버 함수의 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <vector>
using namespace std;
 
int main(){
    vector<int> v;
 
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);
 
    vector<int> :: iterator iter = v.begin()+2;
    vector<int>:: iterator iter2;
    iter2 = v.insert(iter, 100);
 
    for(iter = v.begin() ; iter != v.end() ; ++ iter)
        cout << *iter << " ";
    cout << endl;
    cout << "iter2: " << *iter2 << endl;
    return 0;
}
cs

 

⭐️ insert() 멤버 함수의 사용 실행결과 

1
2
10 20 100 30 40 50 
iter2: 100
cs



📚 출처

공동환(2012), 뇌를 자극하는 C++ STL, 한빛미디어.

Comments