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.