const에 대한 포인터 삭제 (T const *)


91

const 포인터에 관한 기본적인 질문이 있습니다. const 포인터를 사용하여 상수가 아닌 멤버 함수를 호출 할 수 없습니다. 그러나 나는 const 포인터에서 이것을 할 수 있습니다.

delete p;

이것은 본질적으로 상수가 아닌 '메소드'인 클래스의 소멸자를 호출합니다. 왜 이것이 허용됩니까? 이것을 지원하는 것입니까?

delete this;

아니면 다른 이유가 있습니까?

답변:


113

다음을 지원합니다.

// dynamically create object that cannot be changed
const Foo * f = new Foo;

// use const member functions here

// delete it
delete f;

그러나 문제는 동적으로 생성 된 객체에만 국한되지 않습니다.

{
 const Foo f;
 // use it
} // destructor called here

소멸자가 const 객체에 대해 호출 될 수 없다면 우리는 const 객체를 전혀 사용할 수 없습니다.


21
최신 수정 사항을 +1하세요. 이것이 진정한 이유라고 생각합니다. const 객체에 대한 자동 소멸자 호출-delete f와 거의 동일합니다. 여기서 f-const에 대한 포인터.
bayda 2009

const Foo * f또는 Foo const * fFoo에 대한 const 포인터가 아닙니다. const Foo가 더 중요합니다. Foo * const f Foo에 대한 const 포인터입니다.
user11373693

48

이렇게 말하면- 허용 되지 않으면 const_cast를 사용하지 않고 const 객체를 삭제할 방법이 없습니다.

의미 상 const는 객체가 불변이어야 함을 나타냅니다. 그러나 객체를 삭제해서는 안된다는 의미는 아닙니다.


3
소멸자는 다소 폭력적인 방식으로 개체를 변경할 수 있으므로 이전에 알지 못했던 '불변'이라는 단어의 이상한 사용법이 분명합니다.
DarthGizka

1
@DarthGizka 아니, 소멸자는 객체가있는 상태에서없는 상태로 당신을 데려갑니다. C ++는 파괴 후 "돌연변이"를 관찰하는 방법을 정의하지 않습니다
Caleth

@ Caleth : 표준은 소멸자가 완료 될 때까지 개체를 보는 것을 허용하지 않을 수 있지만, 파괴로 인한 부작용은 확실히 볼 수 있습니다. 따라서 '불변'객체의 돌연변이를 관찰 할 수 있도록 상황을 쉽게 조정할 수 있습니다. 미국에서 살인은 시체가 없을 때 기소하기 어렵지만 여전히 살인입니다 (그리고 유죄 판결에 충분한 다른 증거가있을 수 있습니다). 같은 차이.
DarthGizka

6

const 포인터를 사용하여 상수가 아닌 멤버 함수를 호출 할 수 없습니다.

네, 그렇습니다.

class Foo
{
public:
  void aNonConstMemberFunction();
};

Foo* const aConstPointer = new Foo;
aConstPointer->aNonConstMemberFunction(); // legal

const Foo* aPointerToConst = new Foo;
aPointerToConst->aNonConstMemberFunction(); // illegal

상수가 아닌 개체에 대한 const 포인터를 const 개체에 대한 상수가 아닌 포인터와 혼동했습니다.

라고 한,

delete aConstPointer; // legal
delete aPointerToConst; // legal

여기에 다른 답변에 이미 명시된 이유로 인해 둘 중 하나를 삭제하는 것이 합법적입니다.


5

생성자와 소멸자는 '메서드'로 간주되어서는 안됩니다. 클래스의 객체를 초기화하고 분해하는 특수 구조입니다.

'const pointer'는 객체가 살아있는 동안 작업을 수행 할 때 객체의 상태가 변경되지 않음을 나타냅니다.


5

그것을 보는 또 다른 방법 : const 포인터의 정확한 의미는 같은 객체에 대한 참조 나 다른 포인터를 통해 볼 수있는 가리키는 객체를 변경할 수 없다는 것입니다. 그러나 객체가 파괴되면 이전에 삭제 된 객체 차지했던 주소에 대한 다른 모든 포인터 는 더 이상 해당 객체에 대한 포인터가 아닙니다 . 동일한 주소를 저장하지만 해당 주소는 더 이상 객체의 주소가 아닙니다 (실제로 곧 다른 객체의 주소로 재사용 될 수 있음).

이 구분은 C ++의 포인터가 약한 참조처럼 작동하는 경우 더 분명해질 것 0입니다. (이것은 모든 C ++ 프로그램에 적용하기에는 런타임에 너무 많은 비용이 드는 것으로 간주되며 실제로 완전히 신뢰할 수있게 만드는 것은 불가능합니다.)

업데이트 : 9 년 후이 글을 읽으면 변호사 다운 것입니다. 이제 당신의 원래 반응을 이해할 수 있습니다. 돌연변이를 허용하지 않지만 파괴를 허용하는 것은 분명히 문제가 있습니다. const 포인터 / 참조의 묵시적 계약은 그 존재가 자동 가비지 수집이라고하는 대상 개체의 파괴에 대한 블록 역할을 할 것이라는 것입니다.

이에 대한 일반적인 해결책은 거의 모든 다른 언어를 대신 사용하는 것입니다.


const에 대한 포인터가 가리키는 것을 파괴 할 수 없다면, std::unique_ptr<const T>인생 의 결말을 어떻게 처리 합니까?
Caleth

@Caleth 그러면 C ++에서 해결책이 없을 것입니다. 이것은 일반적인 문제의 한 예일뿐입니다. C ++에서 const 한정자는 "대상을 완전히 훼손하고 다른 모든 참조를 무효화하고 정의되지 않은 동작의 소스를 렌더링 할 수있는 한 가지 의미를 제외하고는 대상을 변경할 수 없습니다"를 의미합니다. 이것이 바로 이런 질문이 다른 언어를 고려하는 계기가되어야한다고 생각하는 이유입니다. 다른 기본 접근 방식을 취하지 않으면 해결할 수없는 UB 구멍이 있습니다.
Daniel Earwicker
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.