삽질의 현장/- C++

#026_시(c)시(c)해서 C++?!_객체의 생성과 소멸의 책임

shovelman 2015. 7. 23. 07:45

안녕하세요 삽잡이입니다~!


이번 시간에는 지금껏 제가 공부해오며 간과하던

객체와 소멸에 대한 책임에 대해 알아보도록 하겠습니다...


C#이나 java와 같이 비교적 나온지 얼마 되지 않은 언어들 같은 경우에는

알아서 메모리를 관리해주게 됩니다..

따라서 생성과 소멸에 대해 큰 신경을 쓰지 않아도 됩니다.


하지만, C나 C++ 같이 훨씬 이전에 나온 언어들 같은 경우에는

그 당시 컴파일러를 만드는 기술이 지금보다 안좋았겠죠... 아무튼... 생각을 안한지는 모르겠지만,

객체의 생성이 되며 소멸될때까지 관리되는 heap 메모리 영역에서의

메모리 관리만큼은 개발자에 책임이 있습니다.

내가 응가 쌌으면 내가 치워야져.... 앗... 나의 메모리들이 똥이라는 건 아닙니다... 푸하하하

아... 드럽게시리... 


C에서는 malloc과 free를 통한 동적 메모리 생성 및 소멸을 하고,

C++에서는 new와 delete를 통해 동적 메모리 생성 및 소멸을 합니다.


동적 메모리라는 것은 우리의 필요에 의해 컴파일이 지난 후 실행시간 

즉, runtime 동안에 메모리를 할당해주는 것입니다.


그때 그때 필요에 맞게 stack메모리가 아닌 heap 영역에 우리가 만든 객체들이 만들어지고

그 주소를 우리에게 뿌려주는 것이죠...


아무튼... 현재 이 글을 읽고 계신 분들이

저와 같이 매우 허접한 초보이기에 코드 몇십줄 짜고 컴파일 돌리고 확인하고

왜 안되는지 징징 거리신다면 이런 경험을 체험하지 못하겠지만,


실제 24시간... 아니 365일 내내 돌아가는 서버가 있다고 가정해보도록 하져..

그 매일 달리는 서버의 코드가 객체의 소멸을 간과한 채로 구현되어있다면,

누적이 되고 누적이 되면 분명 큰 화가 다가올 것입니다...


우리는 사전에 좋은 습관을 가지고자... 습관적인 소멸을 위해 노력해야합니다.

지금도 막장으로 코딩하는데 뭐 훗날 갑자기 고치려고 한다고 고쳐지겠습니까... 허허..


코드를 살펴보시죠...


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
// typedef vector<Student *> Svec;
// Svec base; 생성
 
// ... 중략 ...
Student* PreSchool::CreateStu(int type, string name)
{
    Student *temp = 0;
    switch(type)
    {
    case F1:
        temp = new MStudent(name);
        break;
    case F2: 
        temp = new PStudent(name);
        break;
    case F3: 
        temp = new SStudent(name);
        break;
    default : cout<<"잘못 입력 했습니다..."<<endlreturn 0;
    }
    if(temp)
    {
        base.push_back(temp);
    }
    return temp;
}
 
 
cs


굳이 해석이 필요하지는 않지만...

간략하게 Student라는 기반클래스의 파생된 MStudent, PStudent, SStudent

이 세가지의 객체를 생성하고, 반환해주는 기능을 가진 메소드를 소개했습니다.


이 곳에서 보여드리고 싶은 것은...

주석에 달려있는 Student* 형의 vector를 Svec라는 별명을 지어줬는데요...


이 벡터에다가 생성한 객체들을 push_back()하여 저장합니다...

객체를 생성하고 반환시켰는데.... 

그럼 그 반환 시킨 곳에서 소멸해주면 되는것이 아닌가 하는 의문이 들 수 있습니다...

하지만 그렇게 하는 것은 바람직하지 않습니다.


분명히 각 위치에서 객체에 대한 생성에 책임을 가지게 된다면

그 위치에서는 반드시 객체의 소멸에 대한 책임도 가져야됩니다....

맞습니다... 팩토리 패턴을 말하는 것입니다...


만약 이렇게 물을 수 있습니다...

'이 함수를 호출한 곳에서의 vector에 이 반환된 값을 저장시키면 되지 않느냐...'


이는 바람직하지도 않으며 말도 되지 않습니다.

만약 함수를 호출한 곳에서 이 객체가 생성된 반환 값을 저장시킨다고 할지라도

이는 분명 객체가 메모리에 할당된 주소 즉, 참조할 수 있는 위치를 저장하는 것이지

분명 객체 자신을 저장한 것이 아닙니다.


반환 된 곳에서 vector로 이 객체 할당 된 값을 저장했다고 해보죠...

하지만 vector는 그 객체의 위치 정보만을 저장하고 아는 것이지

이 vector에서 erase 하게 된다고 객체가 지워지는 것이 아닙니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
PreSchool::~PreSchool(void)
{
    SIter seek = base.begin();
    SIter end = base.end();
    Student *temp = 0;
    for(; seek != end ; ++seek)
    {
        temp = (*seek);
        delete temp;
    }
}
 
 
cs


동일한 PreSchool 이라는 클래스 내의 소멸자 입니다.

이와 같이 생성과 소멸의 책임은 한 곳에서 이루어져야 됩니다...



다른 고급진 언어들은 알아서 소멸에 대한 책임을 자신들이 가져간다고 했습니다...

하지만 C/C++에서는 소멸의 책임은 전적으로 개발자 입니다.


우리 모두 작은 습관도 초보때 적응하며 

아름다운 코드를 작성해보도록 하여보아요 아하하하하하하


이상 삽잡이였습니다!