C, C++

[C++] new 연산자에 대해

Binceline 2013. 2. 7. 23:21

출처 : http://d.mumbi.net/cpp:new


정의

  • operator new() 를 호출하여 메모리를 할당하고, 생성자를 호출한다.
  • 힙( heap )메모리에 할당된다.

일반 변수

  • new 연산자를 사용해 메모리를 할당한다. 모두 사용한 후 delete 연산자로 해제해 주어야 메모리 누수( leak )가 생기지 않는다.
  • 메모리 할당에 실패시, std::bad_alloc 예외를 던진다. 단, nothrow new 는 0 을 반환한다.
int main( void )
{
    int* p = new int;    // 할당
    delete p;        // 해제
}

배열

  • new[] 연산자를 사용해 메모리를 할당한다. 모두 사용한 후 delete[] 연산자로 해제해 주어야 메모리 누수가 생기지 않는다.
  • new[] 연산자로 할당한 메모리를 delete 연산자로 해제할 경우, 동작이 미정의( undefined )되어 있다.
  • 다차원 배열도 delete[] 연산자로 해제해주면 된다.

1차원 동적 배열

int main( void )
{
    int n = 10;
 
    int* p = new int[n];    // 배열 할당
    delete[] p;        // 배열 해제
}

2차원 동적 배열

int main( void )
{
    int ( *p )[2] = new int[2][2];    // 배열 할당
    delete[] p;        // 배열 해제
}

메모리 지정 new( placement new )

  • 이미 할당된 객체의 메모리에 해당 객체의 생성자를 호출하여 초기화 객체로 만든다.
  • 기존의 메모리를 사용하므로 재할당은 하지 않고 생성자만 호출한다.
  • 직접 메모리를 할당하지 않았기 때문에 delete 연산자로 해제하지 않는다.
/* operator new() 가 다음과 같이 재정의되어 있다.
void* operator new( size_t, void* p )
{
    return p;
}
*/
 
class Point
{
    int x, y;
public:
    Point( int a = 0, int b = 0 ) : x( a ), y( b ) { }
};
 
int main( void )
{
    Point p( 1, 2 );
    new( &p ) Point( 3, 4 );    // 메모리 지정 new
}

nothrow new

  • nothrow new 는 메모리 할당에 실패할 경우, 예외를 던지지 않고 0을 반환한다.
  • 예전 new 는 0을 반환했기 때문에 예전 new 의 오류 검사 코드를 사용하기 위해 #define new new( nothrow ) 로 치환한다.
/*
struct nothrow_t { };
 
nothrow_t nothrow;    // cout << sizeof( nothrow_t ) << endl;    // 사이즈는 1.
 
void* operator new( size_t sz, const std::nothrow_t& )    // 실패시, 0 반환
{
    return malloc( sz );
}
*/
 
// 예전의 코드를 최신의 컴파일러에서 컴파일할 때 사용하는 방법.
// #define new new( nothrow )
 
int main( void )
{
    int* p = new( nothrow ) int;
    if( 0 == p )
    {
        // 실패 처리
    }
 
    delete p;
}

new_handler set_new_handler( new_handler )

  • 메모리 할당을 위한 메모리가 부족할 때, 문제를 처리할 함수를 지정하는 함수이다.
  • 새로운 핸들러를 저장하고, 기존의 핸들러를 반환한다.

new_handler

  • new_handler 는 void( *new_handler )() 의 함수 포인터이다.
  • 메모리 부족 시, new_handler 가 호출되는데, new_handler 는 다음 중 하나를 수행해야 한다.
    • 메모리 부족 문제를 해결해야 한다.
    • 프로그램을 종료하거나, 예외를 던져야 한다.

표준 new 의 구현

  • 표준 new 가 어떻게 구현되었는지 정확히는 알 수 없으나, 다음과 같을 것이다.
void* operator new( std::size_t size ) throw( std::bad_alloc )
{
    if( 0 == size )        // new int[0]; 도 할당된다.
        size = 1;
 
    while( 1 )
    {
        void* p = malloc( size );    // 메모리 할당 시도
        if( 0&nbsp;!= p )
            return p;
 
        new_handler handler = set_new_handler( 0 );    // 새로운 핸들러를 지정하면 기존 핸들러를 반환한다.
        set_new_handler( handler );            // 기존 핸들러를 얻기 위해 다른 핸들러를 지정했으니, 다시 핸들러를 지정한다.
 
        if( 0&nbsp;!= handler )
            handler();
        else
            throw std::bad_alloc();
    }
}

반응형