Maker/Linux

동적 할당 삭제방법(new, delete)

shyun 2012. 6. 28. 15:16

 

* 포인터 : 스택영역에 할당(4byte)되며, 주소값을 가진다.

* 정적 할당 : 메모리의 스택 영역에 할당(시작시 정해진 스코프내에서 고정적으로 스택에 할당되어 사용됨)

* 동적 할당 : 메모리의 힙 영역에 할당 ( 힙 영역은 사용자가 요청한 메모리만큼만 확보 및 삭제를 자유롭게 하기 때문에 정적 할당 보다는 유동적임. 사용자의 측면에서 효율적)

 

스택에 선언되는 변수의 형태들 : int a; char b[10];, int *p; 이런 값들이 정적으로 스택에 자리잡게 된다....

힙에 선언되는 변수의 형태들 : malloc(), char*a = new char[10]; 등.....

 

 

1. 배열 : char a[10];    a[10] 의 값이 스택에 정적할당으로 잡힌다. 

 

2. 포인터 : int a; int *b = &a;    스택에 정적 할당되어 해당 데이터 주소값을 가리킨다.

 

3. 포인터 배열 : int *a = new int[10];  힙에 [10]잡힌다. 스택에 할당된 a가 힙의 [10] 시작 주소를 가리킨다. 메모리 해제 필요.... delete[] a;로 반드시 해제해야 된다.

ex)         int main() {    

                     int *a = new int[10];

                     a[0] = 1; a[1] = 2;.........      사용후    

                     delete[] a;    반드시 해제한다.

 

4. 객체 : AAA a;    AAA 클래스형 a 객체를 생성 (정적)스택에 a가 잡힌다. 해제 필요없음 a.멤버함수(); 접근

 

5. 객체포인터 : AAA *a;    a->멤버함수() 이런식으로 접근, 스택에 할당됨

 

6. 객체 배열 : AAA a[10];     a[i].멤버함수(); 접근한다. 스택에 할당됨

                   AAA a[2] = {AAA(값), AAA(값),}; 이런식으로 생성시초기화 가능함

 

7. 객체 포인터 배열 : AAA *ap[10];     for문내 ap[i] = new AAA(값); 로 초기화, 스택에 ap[i] 주소값을 가지는 값들이 잡히며, 힙 영역에 [10]만큼 잡힌다.    ap[i]가 각각의 힙영역 [i]을 가리킨다.

반드시 해제 필요하다..    for문 내  delete ap[i];   이런식으로 해제한다.

ex)          class AAA { ~~~~~~~~~~~ };

              int main() {

                          AAA *ap[10];

                          for(int i = 0; i<10; i++) {

                                   ap[i] = new AAA(초기화구문);

                           }     // 힙에 new 할당

                          ap[1]->print();   ................  사용 후

                          for(int j = 0; j<10; j++) {

                                delete ap[j];

                           }       // 반드시 해제한다.....

                          return 0;

               }

 

결론을 설명하면, 포인터변수든 일반 변수든 스택에 잡힌다.....  단 동적으로 힙에 new할당된 배열 등에 대한 주소를 스택에 할당된 포인터변수의 값에 보관하고 다이렉트로 연결만 해주는 것이다.

 

int *a = new int[10];

[                stack영역                 ]  [                      힙 영역                     ]

[  포인터변수 a = 0x1000번지 저장   ]  [  int[10]저장 int[10]주소는 0x1000번지   ]

   |__________________________________________________________↑

      이렇게 힙영역 int[10] 가리키면서 참조하여 액세스한다.....

 

객체포인터배열은 동적 생성과 동시 초기화가 불가능하다..

AAA *a = new AAA[2] = {AAA(값),AAA(값),};       // ERROR

AAA a[2] = {AAA(값),AAA(값),};                       // OK

 

객체포인터배열은 디폴트생성자가 필요하다,

AAA *a = new AAA[2]; 를 했을때 a[0]과 a[1]의 2개의 객체가 생성된 상태이기 떄문에 그 상황의 생성자를 가져야 된다, 하지만 초기화가 불가능하므로 디폴트 생성자를 호출하게 된다. 위의 디폴트생성자는 AAA(){}가 되겠다..  하지만 이건 걱정하지 않아도 된다 유저가 default생성자를 생성하지 않아도 컴파일러가 알아서 default생성자, 소멸자,  복사생성자를 만들어준다.

AAA(){} 생성자

~AAA(){} 소멸자

AAA(AAA&a){} 복사생성자


[출처] http://blog.naver.com/copynull?Redirect=Log&logNo=10075173365