프로그래밍/C++
벡터(Vector) 2
hscho00
2020. 6. 23. 21:38
개체를 직접 보관하는 벡터의 문제점
1. 용량을 초과하여 재할당 될 때마다
2. 대입 연산자로 벡터의 사본을 만들때마다
개체를 전부 복사해야 하기 때문에, 개체의 크기가 커지면 메모리 복사량도 덩달아 많아지는 문제
포인터를 저장하는 벡터를 쓰면 개체를 직접 보관하는 벡터에 비해 재할당 시 복사량이 적다!
대신 모든 요소에 대해 delete를 꼭 호출할 것!
> 또한 지운 후에 이 포인터들을 계속 사용하면 안 됨!!
벡터의 장점
순서에 상관 없이 색인만 알면 요소에 임의적으로 접근 가능(앞에서부터 찾을 필요 없다)
제일 마지막 위치에 요소를 빠르게 삽입 및 삭제(메모리 재할당이 없다는 가정 하에)
벡터의 단점
중간에 요소 삽입 및 삭제는 느림
재할당 및 요소 복사에 드는 비용
> 얼마나 할당할 지 사이즈를 알고 있다면 추가적인 재할당을 막기 위해 반드시 reserve를 해주자
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
#include <iostream>
#include <vector>
using namespace std;
class Score
{
public:
Score(int score, const string& classname)
: mScore(score), mClassname(classname)
{
}
int GetScore() const
{
return mScore;
}
void SetScore(const int score) // 실수로 변경되는 것을 막기 위한 const
{
mScore = score;
}
const string& GetClassname() const
{
return mClassname;
}
private:
int mScore;
string mClassname;
};
void PrintVector(const vector<Score>& scores)
{
for (vector<Score>::const_iterator iter = scores.begin(); iter != scores.end(); ++iter)
cout << iter->GetClassname().c_str() << " : " << iter->GetScore() << endl;
cout << "Capacity: " << scores.capacity() << ", Size: " << scores.size() << endl;
cout << "====================================" << endl;
}
void PrintVector(const vector<Score*>& scores)
{
for (vector<Score*>::const_iterator iter = scores.begin(); iter != scores.end(); ++iter)
cout << (*iter)->GetClassname().c_str() << " : " << (*iter)->GetScore() << endl;
cout << "Capacity: " << scores.capacity() << ", Size: " << scores.size() << endl;
cout << "====================================" << endl;
}
int main()
{
cout << "===========Object Vector============" << endl;
vector<Score> scores; // 개체(Object)를 직접 담는 vector
scores.reserve(5); // capacity 5
scores.push_back(Score(30, "C++")); // 스택에 개체 생성 후 vector로 복사해 넣음
scores.push_back(Score(40, "Algorithm"));
scores.push_back(Score(50, "Java"));
scores.push_back(Score(60, "Data Comm"));
scores.push_back(Score(70, "Android"));
PrintVector(scores);
vector<Score>::iterator iter = scores.begin();
while (iter != scores.end())
{
if (iter->GetClassname() == "Java")
{
// erase() 후 뒤에 있는 요소들이 한 칸씩 땡겨짐
// iter는 변하지 않았어도 "Java" 다음 요소를 가리킴
// 만약 for 문에서 erase 했을 경우 증감식(++iter) 때문에 "Java" 다음 요소를 건너 뛰었을 것임
iter = scores.erase(iter);
}
else
{
// erase 하지 않았을 때만 iter 증가
iter++;
}
}
PrintVector(scores);
// 중간에 erase 안했으니 for문을 써서 처음부터 끝까지 빼먹지 않고 훑을 수 있다
for (vector<Score>::iterator it = scores.begin(); it!= scores.end(); ++it)
{
Score score = *it; // 복사 생성자 호출. 사본을 만드는 셈
if (score.GetScore() == 30)
{
score.SetScore(100); // 사본의 값을 수정해봤자 원본은 안바뀜
}
}
PrintVector(scores);
iter = scores.begin();
cout << iter->GetClassname().c_str() << endl; // 반복자를 "포인터"처럼 쓸 수가 있다
// 반복자 때문에 개체가 복사되는 일은 없음
scores.clear();
cout << endl << "===========Pointer Vector===========" << endl;
vector<Score*> newScores;
newScores.reserve(2);
newScores.push_back(new Score(30, "C++"));
newScores.push_back(new Score(87, "Java"));
newScores.push_back(new Score(41, "Android")); // 재할당 되도 개체를 담은 벡터에 비해 복사량이 적다
PrintVector(newScores);
vector<Score*>::iterator newIter = newScores.begin();
while (newIter != newScores.end())
{
if ((*newIter)->GetClassname() == "Java")
{
newIter = newScores.erase(newIter);
}
else
{
// erase 하지 않았을 때만 iter 증가
newIter++;
}
}
PrintVector(newScores);
for (vector<Score*>::iterator it = newScores.begin(); it != newScores.end(); ++it)
{
Score* score = *it; // 주소를 받아옴
if (score->GetScore() == 30)
{
score->SetScore(100); // 원본 수정!!
}
}
PrintVector(newScores);
// 꼬옥! 포인터 벡터 삭제하기
for (vector<Score*>::iterator iter = newScores.begin(); iter != newScores.end(); ++iter)
delete *iter;
newScores.clear();
return 0;
}
|
cs |
출처 : 포큐아카데미 C++ 언매니지드 프로그래밍