티스토리 뷰

낙서

C++ 동적할당의 고찰

nodeal 2017.08.07 15:01

C언어와 C++ 모두 공통적으로 포인터를 이용하여 프로그래밍이 가능하고 C++에서는 객체지향의 개념이 더해지면서 동적할당을 통해 객체를 관리할 수 있다.


간혹 C++에 관하여 찾다 보면 되도록 new를 이용하여 동적할당 하는 것을 피하라고 하는데 이유가 뭘까?


class Foo {
    private:
    Bar bar;
}; // End of scope


가령 이런 코드가 있다고 생각해보자. bar는 객체로써 사용될 수 있지만 포인터는 아니다.

이렇게 선언된 객체는 스코프가 종료되는 시점에서 자동으로 해제된다. 마치 GC처럼.

객체의 접근이 불가능 해지는 시점부터 해제되는 GC보다 오히려 좀 더 직관적인 해제 타이밍을 알 수 있다.


C++이 포인터나 뭐나의 이유로 어렵다고 하는데, 생각보다 똑똑한 언어가 아닌가.


그럼 이런 경우는 어떨까,

for (int i = 0; i < 10; i++) {
    Bar bar;
} // End of scope

역시 저 한 순환이 마칠때마다 bar는 해제된다. 하지만 필요에 따라 그렇지 않을 때도 있다.


반복문 또는 조건문에서 사용된 객체가 밖에서도 필요했다면, 해당 분기의 앞에서 선언한 후 이후에 접근하는 방법은 어떨까,

Point point(10, 10);
if (condition) {
    doSomething(point);
}
doAnotherThing(point);

일반적인 방법에서의 구현이였다. 하지만 포인터를 이용했다면 delete 이전까지 살아있는 주소에 대해 언제든 접근이 가능했기에 굳이 저럴 필요까지는 없었을 것이다. 또한, 이후 point가 더 이상 필요하지 않았다면 도리어 스코프가 끝날 때 까지 살아있는 리소스 낭비일 것이다.


만약 Point와 같은 객체가 아닌 엄청나게 큰 이진 파일을 가지고 있는 객체라고 생각해보자.

void foo() {
    Binary binary = Binary(getBinary()); // Size: 10G

    if (condition) {
        doSomething(binary);
    }

    doAnotherThing(binary);

    /* 1000 lines after... */
} // End of scope

10G에 해당하는 이진 자료를 가지고 있는 상황이다. 스코프의 종료는 1000줄 이후에 생기고 그동안 뭐 여러 다른 작업들을 할 것이다. 물론 이렇게 짜는게 좋진 않지만..


스코프의 마치는 지점까지 살아있는 저 객체는 doAnotherThing(Binary) 이후 단 한번도 사용되지 않았다고 생각해보자. 굳이 필요하지도 않겠지만 언어의 입장에서 해제시킬 수는 없는 노릇일 것이다.


이때 포인터를 이용해서 doAnotherThing(Binary) 후에 delete를 해준다면

void foo() {
    Binary *binary = new Binary(getBinary()); // Size: 10G

    if (condition) {
        doSomething(binary);
    }

    doAnotherThing(binary);
    delete binary;

    /* 1000 lines after... */
} // End of scope

저 1000줄의 멍청한 메소드가 마칠때 까지 살아있지 못하고 사용이 끝난 후에 바로 해제할 수 있다.



사실 현실적인 부분에서 저런 10G에 해당하는 무언가를 불러올 일도 없을테고, 실행시간이 오래걸리는 1000줄짜리 메소드를 만들 일도 없을 것이다. 좀 극단적인 예시였지만 뭐가됐든 똑같은 경우고 정수형 변수 하나하나 목숨걸고 해제하게끔 가르치는 판국에서 동적할당의 확실한 사용방법이 중요하다.


어떤 방법으로던 메모리 해제는 전적으로 프로그래머의 재량이다. 확실한 해제 타이밍이 있는 경우에 동적할당을 적용할 수도 있고, 그렇지 않은 경우에서 자연히 스코프가 종료될 때 해제되게끔 할 수도 있다.

다만 두 경우 모두 작성한 사람뿐만 아니라 많은 사람들에게 직관적으로 납득될만한 상황에서 적용되어야 할 것이다.


동적할당을 사용하고 그렇지 않은 경우는 다른 이유도 있다. 객체의 크기를 예측할 수 없을 때 동적할당을 하라는 등 여러가지 예시가 많다. 이런건 나중에 알아보던가 그냥 구글에 쳐보자.


c++ why should avoid dynamic allocation 이란 검색어로 한국 사이트가 안나와서 답답했다.

뭐 가장 재밌던 검색결과는 그냥 C++은 new를 최소화해야하는 언어라는것..

Java하던 사람이 오면 복창터질 일이다.


'낙서' 카테고리의 다른 글

C++ #pragma once  (0) 2017.10.19
C++ 포인터 주소값 저장하기  (0) 2017.10.12
C++ 동적할당의 고찰  (0) 2017.08.07
[HOWTO] Windows8 설치하기  (0) 2013.12.30
[HOWTO] 안드로이드에 우분투 설치하기  (0) 2013.12.30
[HOWTO] ARM용 GCC만들기  (0) 2013.12.30
댓글
댓글쓰기 폼