왜 delete는 포인터를 NULL로 만들지 않는가
C++로 프로그래밍을 하다 보면, 보통 delete 연산 후에 해당 포인터를 NULL로 만들어 줘야 한다.
그렇다면, ‘언어차원에서, delete를 했을 때 NULL로 세팅해 줬으면 이런 귀찮은 작업을 피할 수 있는데, 왜 그렇게 하지 않았을까?
일단, c++ 창시자인 스트롭스트룹님이 한 이야기를 보자, [1]
delete p; // ... delete p; |
… 부분에서 p에 관한 아무 작업도 하지 않았다면, C++은 심각한 에러를 낸다. C++은 이에 대해 효율적인 방어수단이 없기 때문이다.
pointer를 zero(0 or NULL)로 만드는 것이 나쁜 것은 아니지만, 위의 문제를 해결해 주지는 않는다.
delete 연산자가 lvalue(좌변)이 필요 하지 않은 이유가 있다.
일단 아래의 코드를 보면,
delete p+1; delete f(x); |
delete 구현은 위처럼 zero로 할당할 수 없는 포인터를 가질 수 있다. 이런 경우는 NULL로 세팅할 수 없다.
그리고 혹자는 이런 말을 한다.
성능 문제를 놓고 볼 때, delete를 한 이후에 바로 scope(범위)를 벗어나게 되면, 포인터를 NULL로 세팅하는 것이 시간만 소모할 뿐이다. C++은 “그것이 필요 없는가? 그렇다면 그에 대한 대가도 지불할 필요가 없다” 라는 이데올로기를 갖고 있다.[2]
그리고 아래와 같은 말을 한다.
C++ explicitly allows an implementation of delete to zero out an lvalue operand, and I had hoped that implementations would do that, but that idea doesn't seem to have become popular with implementers. |
다시 말해서, C++에서 delete 구현시 포인터를 명시적으로 zero로 만드는 것이 가능하고, 나 또한 그렇게 하고 싶다.
그러나 이 아이디어가 모든 사람들에게 인기가 있을 것 같진 않다.
그럼 어떻게 하느냐?
만약 pointer를 zero로 만들어 사용하고 싶으면, 아래와 같이 destroy와 같은 함수를 사용한다.
template<class T> inline void destroy(T*& p) { delete p; p = 0; } |
위와 같이 참조자로서 포인터를 넘겨주면, rlvaue(우변)를 파라미터로 넘겨서 삭제하지 못하게 해준다.
혹은 [3]에서 처럼 delete[]에 대해서도 구현 가능하다.
template< class T > void SafeDelete( T*& pVal ) |
사실, 이것보다 스마트 포인터(auto_ptr, scoped_ptr, shared_ptr)를 사용하는 것이 훨씬 좋다!!!
참조
1. http://www2.research.att.com/~bs/bs_faq2.html#delete-zero
2. http://stackoverflow.com/questions/704466/why-doesnt-delete-set-the-pointer-to-null
3. http://stackoverflow.com/questions/1265666/reason-why-not-to-have-a-delete-macro-for-c