2009-04-01 5 views
108

삭제 후 NULL 포인터에 대한 자동 설정이 표준에 포함되지 않은 이유는 언제나 궁금합니다. 이것이 처리되면 잘못된 포인터로 인한 많은 충돌이 발생하지 않습니다. 그러나 표준이 제한된 왜 나는 이유 중 몇 가지를 생각할 수 있다고 한 :포인터를 NULL로 설정하면 삭제되지 않는 이유는 무엇입니까?

  1. 성능 :

    추가 명령이 delete 성능이 저하 될 수 있습니다.

  2. const 포인터 때문일 수 있습니까?

    그런데이 표준은 내가 추측 한이 특별한 경우에 대해 뭔가를했을 수 있습니다.

는 사람이 허용하지 않는 정확한 이유를 알고 있나요?

답변

138

Stroustrup himself 답. 발췌 :

C++ 명시 적으로 에게 좌변 피연산자를 제로로 삭제의 구현을 허용하고, 나는 구현 하지만 그 생각은 과 함께 인기를 끌고있다하지 않는 것, 그렇게 할 것이라고 을 기대했다 구현 자.

그러나 그가 제기하는 주요 문제는 delete의 인수가 lvalue 일 필요가 없다는 것입니다.

12

정말 필요하지 않기 때문에 포인터가 아닌 포인터를 가져 오는 삭제가 필요하기 때문입니다.

+1

포인터를 참조하십시오. –

+0

사실 그렇지만 동일한 오버 헤드가 발생합니다. – snemarch

5

포인터 배열이 있고 두 번째 작업이 빈 배열을 삭제하는 경우 메모리가 해제 될 때 각 값을 null로 설정하지 않아도됩니다. null이되기를 원한다면 .. null을 쓰자. :)

54

먼저 null로 설정하려면 메모리 저장 변수가 필요하다. 사실 변수에 포인터가 있지만 보통 방금 ​​계산 된 주소의 개체를 삭제하려고 할 수 있습니다. 삭제를 무효화하는 것은 불가능합니다.

그러면 성능이 향상됩니다. 삭제가 완료된 직후에 포인터가 범위를 벗어나는 방식으로 코드를 작성했을 수 있습니다. null로 채우는 것은 단지 시간 낭비입니다. 그리고 C++은 "필요하지 않습니다. 그러면 돈을 지불 할 필요가 없습니다"라는 이데올로기가있는 언어입니다.

안전이 필요한 경우 다양한 스마트 포인터가 서비스에 제공되거나 직접 작성하는 것이 더 좋습니다.

+4

좋은 점 wrt 계산 된 주소입니다. 자주 볼 수없는 항목 일 수도 있습니다. – snemarch

+0

당신은 때로는 그냥 계산 된 주소. ??? – Destructor

+0

@PravasiMeet 아니, 나는'delete (ptr + i)'와 같은 것을 의미한다. – sharptooth

35

메모리를 가리키는 포인터가 여러 개있을 수 있습니다. delete에 대해 지정한 포인터가 null로 설정되었지만 다른 모든 포인터는 null이 아닌 경우 잘못된 보안을 생성합니다. 포인터는 주소, 숫자 이상입니다. 참조 연산이없는 int 일 수도 있습니다. 내 요점은 또한 당신이 방금 삭제 한 동일한 메모리를 참조하는 것들을 찾으려면 모든 단일 포인터를 스캔해야 할 것입니다, 그리고 그들을 밖으로 또한 null. 컴퓨터가 그 주소에 대한 모든 포인터를 스캔하여 널 (null)로 만드는 것은 언어가 그 용도로 설계되지 않았기 때문에 집중적입니다. (다른 언어가 비슷한 방법으로 다른 목표를 달성하기 위해 참조를 구성하더라도.)

17

포인터를 둘 이상의 변수에 저장할 수 있습니다.이 중 하나를 NULL로 설정하면 다른 변수에 잘못된 포인터가 남습니다. 그래서 당신은 정말로 많이 얻지 못합니다. 당신은 틀린 보안 감각을 만들 가능성이 더 큽니다.

그 외에, 당신은 당신이 원하는 것을 그 자신 만의 함수를 만들 수 있습니다

template<typename T> 
void deleten(T *&ptr) { 
    delete ptr; 
    ptr = NULL; 
} 
4

C++는 새로운 자신의 연산자를 정의하고 그래서 예를 들어 그들은 자신의 풀 할당을 사용 삭제할 수 있습니다. 이렇게하면 엄격하게 주소는 아니지만 풀 배열의 색인이라고하는 항목으로 new 및 delete를 사용할 수 있습니다. 이 문맥에서 NULL (0) 값은 법적 의미를 가질 수 있습니다 (풀의 첫 번째 항목 참조).
삭제를 NULL로 설정하면 해당 인수에 항상 자동으로 NULL이 설정되는 것은 아닙니다. 즉, 값을 잘못된 값으로 설정하십시오. 유효하지 않은 값은 항상 NULL이 아닐 수도 있습니다.

3

포인터를 NULL로 자동 설정해도 잘못된 포인터 사용으로 인한 대부분의 문제는 해결되지 않습니다. 피할 수있는 유일한 충돌은 두 번 삭제하려고하는 경우입니다. 그러한 포인터에서 멤버 함수를 호출하면 어떻게 될까요? 그것은 여전히 ​​충돌합니다 (멤버 변수에 액세스한다고 가정). C++에서는 NULL 포인터에 대한 함수를 호출하지 못하도록 제한하지 않으며 성능 관점에서 함수를 호출해야하지도 않습니다.

4

C++의 철학은 "사용하는 경우에만 비용을 지불합니다"입니다. 나는 그것이 당신의 질문에 대답 할 것 같아요.

또한 때로는 삭제 된 메모리를 복구 할 수있는 자신의 힙을 가질 수 있습니다. 또는 때로는 포인터가 모든 변수의 소유가 아닙니다. 또는 몇 가지 변수에 포인터가 저장되어 있습니다. 0 일 수도 있습니다.
알다시피 많은 문제와 가능한 문제점이 있습니다.

7

delete은 대부분 소멸자에서 사용되며,이 경우 멤버를 NULL로 설정하는 것은 의미가 없습니다. 나중에 몇 줄이면 }이 닫히면 더 이상 구성원이 존재하지 않습니다. 대입 연산자에서 삭제는 일반적으로 어쨌든 할당이 뒤 따른다.

또한, 불법 다음 코드를 렌더링 것 : 여기

T* const foo = new T; 
delete foo; 
4

또 다른 이유; delete가 인수를 NULL로 설정한다고 가정하십시오.

int *foo = new int; 
int *bar = foo; 
delete foo; 

표시 줄을 NULL로 설정해야합니까? 이것을 일반화 할 수 있습니까?

-2

나는이 질문에 이상한 대답을하는 사람들을 봅니다.

ptr = NULL; 그런 간단한 명령문으로 인해 성능 지연이 발생할 수 있습니까?

또 다른 대답은 동일한 메모리 위치를 가리키는 여러 개의 포인터를 가질 수 있다는 것입니다. 확실하게 할 수 있습니다.이 경우 하나의 포인터에 대한 삭제 작업은 해당 포인터 만 NULL (삭제가 포인터 NULL을 만드는 경우)으로 만들고 다른 포인터는 NULL이 아니며 사용 가능한 메모리 위치를 가리키게됩니다.

이 솔루션은 사용자가 동일한 위치를 가리키는 포인터를 모두 삭제해야합니다. 내부적으로 메모리가 이미 비어 있지 않은지 확인해야합니다. 포인터 만 NULL로 만듭니다.

Stroustrup은 이러한 방식으로 작동하도록 삭제를 디자인했을 수 있습니다. 그는 프로그래머가이 문제를 처리 할 것이라고 생각했습니다. 그래서 그는 무시했습니다.

관련 문제