UFO ET IT

삭제되지 않은 객체에 대해 소멸자가 호출되는 이유는 무엇입니까?

ufoet 2020. 12. 9. 20:57
반응형

삭제되지 않은 객체에 대해 소멸자가 호출되는 이유는 무엇입니까?


struct A
{
    ~A() = delete;
};

int main()
{
    new A{};
}

다음 오류 메시지와 함께 컴파일되지 않습니다.

오류 : 삭제 된 함수 'A :: ~ A ()'사용 new A {};

내가 이해했듯이 객체를 파괴하지 않고 왜 소멸자를 호출하려고합니까?

GCC 8.1.0으로 컴파일 됨

g++ -std=c++17 -O2

이것은 gcc 버그 57082 입니다.


아래에서 위로 가자.

[dcl.fct.def.delete] / 2 :

삭제 된 함수를 선언하는 것 외에 암시 적으로 또는 명시 적으로 참조하는 프로그램의 형식이 잘못되었습니다.

분명히 우리는 ~A()명시 적으로 언급하지 않습니다 . 암시 적으로 언급하고 있습니까? [class.dtor] / 12 :

소멸자가 암시 적으로 호출 됨

  • 프로그램 종료시 ([basic.start.term]) 정적 저장 기간 ([basic.stc.static])으로 구성된 객체의 경우,
  • 스레드 종료시 스레드 저장 기간 ([basic.stc.thread])으로 구성된 객체의 경우
  • 객체가 생성 된 블록 ([stmt.dcl])이 종료 될 때 자동 저장 기간 ([basic.stc.auto])으로 구성된 객체의 경우,
  • 생성 된 임시 객체의 수명이 끝날 때 ([conv.rval], [class.temporary]).

또는 [expr.new] / 20 :

는 IF 새로운 표현은 클래스 타입의 오브젝트의 배열을 생성 소멸자 잠재적 호출된다.

그런 것들이 있습니까? 아니요, 여기에는 자동, 정적 또는 스레드 저장 기간이있는 개체가 없으며 구성된 임시 개체도없고 배열을 만드는 new-expression 도 없습니다 . 여기에는 A집계 초기화중인 동적 저장 기간이 있는 개체가 하나뿐입니다 .

우리는 명시 적으로도 암시 적으로도 언급하지 않았기 때문에 우리는 ~A()그 규칙을 넘어 설 수 없습니다. 따라서 gcc 버그입니다. gcc는 이 규칙에 관한 한 동일한 의미를 갖는 new A;and를 허용 new A();합니다.


아마도 여기에 gcc 버그 일 것입니다.

표준은 새 표현식이 배열 [expr.new]를 만들 때 소멸자가 잠재적으로 호출되도록 지정합니다 .

new-expression이 클래스 유형의 개체 또는 개체 배열을 만드는 경우 할당 함수, 할당 해제 함수 및 생성자에 대한 액세스 및 모호성 제어가 수행됩니다. new-expression이 클래스 유형의 객체 배열을 생성하면 소멸자가 잠재적으로 호출됩니다.

내 강조

gcc는 비 배열을 생성 할 때도이 규칙을 적용하며 이는 암시 적으로 표준 규칙이 아닙니다. 아래의 주석 덕분에 gcc는 정반대의 작업을 수행하는 것 같습니다. 비 배열을 만들 때 소멸자가 잠재적으로 호출 된 것으로 간주하고 배열을 만들 때 소멸자를 확인하지 않습니다.


내가 알 수있는 한, 예제에서는 어떤 객체도 파괴되지 않으며 표현식이 다음과 같이 변경되면 컴파일됩니다. new A;

컴파일되지 않은 예제 코드는 GCC의 버그라고 생각합니다. Clang은 잘 컴파일합니다 .


새로 추가 된 언어 변호사 태그에 대한 답변입니다.

중요한 표준 규칙은 [class.dtor]에 있습니다.

소멸자가 암시 적으로 호출 됨

... 동적 이외의 다른 저장 기간과 관련하여 적용되지 않는 경우 ...

... 소멸자는 new-expression (5.3.4)에 의해 할당 된 생성 된 객체에 대해 delete-expression (5.3.5)을 사용하여 암시 적으로 호출됩니다. 호출 컨텍스트는 delete-expression입니다. [참고 : 클래스 유형의 배열에는 각각 소멸자가 호출되는 여러 하위 객체가 포함됩니다. — end note] 소멸자를 명시 적으로 호출 할 수도 있습니다. 소멸자는 호출되거나 5.3.4, 12.6.2 및 15.1에 지정된대로 호출 될 수 있습니다.

5.3.4는 [expr.new]로

... new-expression이 클래스 유형의 객체 배열을 생성하면 소멸자가 잠재적으로 호출됩니다 (12.4).

적용되지 않습니다.

12.6.2는 [class.base.init]이며

비 위임 생성자에서 클래스 유형의 잠재적으로 생성 된 각 하위 객체에 대한 소멸자가 잠재적으로 호출됩니다 (12.4).

적용되지 않는

15.1은 [except.throw]로 예외 객체가 소멸되는 방법을 지정하며 적용되지 않습니다.

결론 : 섹션 5.3.4, 12.6.2 및 15.1 없음. 이 경우에 적용되는 규칙을 포함하고 소멸자가 호출되지 않으며 delete-expression도 없습니다. 따라서 소멸자는 잠재적으로 호출되지 않으므로 소멸자를 삭제할 수 있도록 잘 구성되어 있습니다.

참고 URL : https://stackoverflow.com/questions/51974783/why-is-the-destructor-called-for-an-object-that-is-not-deleted

반응형