본문 바로가기

[ C/ C++ 프로그래밍 ]/[ STL ]

[ 혼연 정리 ] 시퀀스 컨테이너 - 4 [ 벡터 ]


ㅇ 사용자 정의 요소  --> 심도있게보자

 - 클래스 객체를 요소로 가지는 벡터도 만들수 있다.


1 #include <iostream>
2 #include <vector>
3
4 using namespace std;
5
6 class Time
7 {
8 protected:
9      int hour,min,sec;
10 public:
11      Time(int h,int m,int s) { hour=h;min=m;sec=s; }
12      void OutTime() { printf("%d:%d:%d ",hour,min,sec); }
13 };
14
15 template<typename C>
16 void dump(const char *desc, C c)
17 {
18      cout.width(12);cout << left << desc << "==> ";
19      for (unsigned i=0;i<c.size();i++) { c[i].OutTime(); }
20      cout << endl;
21 }
22
23 void main()
24 {
25      vector<Time> vt;
26 vt.push_back(Time(1,1,1));
27      vt.push_back(Time(2,2,2));
28      dump("요소2개",vt);
29 }



- 벡터에 저장된 객체들은 벡터가 파괴될 때 같이 파괴되므로 Time 객체를 별도로 파괴할 필요는 없다.
- 벡터에 직접 객체를 저장하는 것보다는 객체의 포인터를 저장하는 것이 성능상 유리하며 훨씬 더 일반적이다.

- 동적할당 예)

1 #include <iostream>
2 #include <vector>
3
4 using namespace std;
5
6 class Time
7 {
8 protected:
9      int hour,min,sec;
10 public:
11      Time(int h,int m,int s) { hour=h;min=m;sec=s; }
12      void OutTime() { printf("%d:%d:%d ",hour,min,sec); }
13 };
14
15
16 template<typename C>
17 void dump(const char *desc, C c)
18 {
19      cout.width(12);cout << left << desc << "==> ";
20      for (unsigned i=0;i<c.size();i++) { c[i]->OutTime(); }
21      cout << endl;
22 }
23
24 void main()
25 {
26      vector<Time *> vt;
27      vt.push_back(new Time(1,1,1));
28      vt.push_back(new Time(2,2,2));
29      dump("요소2개",vt);
30      vector<Time *>::iterator it;
31      for (it=vt.begin();it!=vt.end();it++) {
32           delete *it;
33      }
34 }




vt 객체는 메모리에 다음과 같이 생성될 것이다.



- 포인터를 가지는 벡터를 파괴할 때는 각 포인터가 가리키는 객체를 직접 파괴해야 한다. --> 그렇지 않으면 메모리 누수 발생
- 임의의 타입에서 일정 조건을 만족하는 타입만 저장할 수 있다.

- 임의 조건을 만족하는 타입 예)

1 #include <iostream>
2 #include <vector>
3 #include <algorithm>
4
5 using namespace std;
6
7 class Dynamic
8 {
9 private:
10      char *ptr;
11 public:
12      Dynamic() {
13           ptr=new char[1];
14           ptr[0]=0;
15      }
16      Dynamic(const char *str) {
17           ptr=new char[strlen(str)+1];
18           strcpy(ptr,str);
19      }
20      Dynamic(const Dynamic &Other) {
21           ptr=new char[strlen(Other.ptr)+1];
22           strcpy(ptr,Other.ptr);
23      }
24      Dynamic &operator =(const Dynamic &Other) {
25           if (this != &Other) {
26               delete [] ptr;
27               ptr=new char[strlen(Other.ptr)+1];
28               strcpy(ptr,Other.ptr);
29           }
30           return *this;
31      }
32      int operator ==(const Dynamic &Other) const {
33           return strcmp(ptr,Other.ptr);
34      }
35      int operator <(const Dynamic &Other) const {
36           return strcmp(ptr,Other.ptr) < 0;
37      }
38      virtual ~Dynamic() {
39           delete [] ptr;
40      }
41      virtual void OutDynamic() {
42           cout << ptr << ' ';
43      }
44 };
45
46 template<typename C>
47 void dump(const char *desc, C c)
48 {
49      cout.width(12);cout << left << desc << "==> ";
50      for (unsigned i=0;i<c.size();i++) { c[i].OutDynamic(); }
51      cout << endl;
52 }
53
54 void main()
55 {
56      vector<Dynamic> vt;
57      Dynamic a("dog");
58      Dynamic b("cow");
59      vt.push_back(a);
60      vt.push_back(b);
61      dump("요소2개",vt);
62 }



- 디폴트 생성자, 변환 생성자, 복사 생성자(깊은복사), =대입연산자, ==, < 비교 연산자, 가상 파괴자 등이 정의 되어 있어야 한다.

- 검색, 정렬 예)


1 #include <iostream>
2 #include <vector>
3 #include <algorithm>
4
5 using namespace std;
6
7 class Dynamic
8 {
9      friend struct DynCompare; 10      friend struct DynFind;
11 private:
12       char *ptr;
13 public:
14       Dynamic() {
15              ptr=new char[1];
16              ptr[0]=0;
17       }
18       Dynamic(const char *str) {
19              ptr=new char[strlen(str)+1];
20              strcpy(ptr,str);
21       }
22       Dynamic(const Dynamic &Other) {
23              ptr=new char[strlen(Other.ptr)+1];
24              strcpy(ptr,Other.ptr);
25       }
26       Dynamic &operator =(const Dynamic &Other) {
27              if (this != &Other) {
28                    delete [] ptr;
29                    ptr=new char[strlen(Other.ptr)+1];
30                    strcpy(ptr,Other.ptr);
31              }
32              return *this;
33       }
34       int operator ==(const Dynamic &Other) const {
35              return strcmp(ptr,Other.ptr);
36       }
37       int operator <(const Dynamic &Other) const {
38              return strcmp(ptr,Other.ptr) < 0;
39       }
40       virtual ~Dynamic() {
41              delete [] ptr;
42       }
43       virtual void OutDynamic() {
44             cout << ptr << ' ';
45       }
46 };
47
48 template<typename C>
49 void dump(const char *desc, C c)
50 {
51       cout.width(12);cout << left << desc << "==> ";
52       for (unsigned i=0;i<c.size();i++) { c[i]->OutDynamic(); }
53       cout << endl;
54 }
55
56 struct DynCompare {
57      bool operator()(Dynamic *a, Dynamic *b) const {
58           return strcmp(a->ptr, b->ptr)<0;
59      }
60 };
61
62 struct DynFind {
63     bool operator()(Dynamic *a) const {
64           return strcmp(a->ptr, "cat")==0;
65      }
66 };
67
68 void main()
69 {
70      vector<Dynamic *> vt;
71      vt.push_back(new Dynamic("dog"));
72      vt.push_back(new Dynamic("cow"));
73      dump("요소2개",vt);
74
75      Dynamic d("cat");
76      puts(find_if(vt.begin(),vt.end(),DynFind())==vt.end() ? "없다":"있다");
77      sort(vt.begin(), vt.end(), DynCompare());
78      dump("정렬후",vt);
79
80      vector<Dynamic *>::iterator it;
81      for (it=vt.begin();it!=vt.end();it++) {
82           delete *it;
83      }
84 }




- 벡터에 포인터를 저장하는 것이 가능하기는 하지만 여러가지 신경써야 할 것들이 많고 불편하기 때문에 벡터에는 통상 값을 저장하는 것이 권장된다.


ps : 출처 및 자세한 내용은  www.WinAPI.co.kr 참고