문제

내가 파괴자를 명시 적으로 호출한다면 (myObject.

OK 일부 코드 :

class Object
{
   virtual ~Object()
   {}
};

class Widget : public Object
{
   virtual ~Widget()
   {}
};

...
Object* aWidget = new Widget(); //allocate and construct
aWidget->~Object(); //destroy and DON'T deallocate

나는 단지 객체를 삭제할 수 있다는 것을 알고 있지만 원하지 않습니다. 할당 된 메모리를 중요한 최적화로 사용하고 싶습니다.

감사!

도움이 되었습니까?

해결책

대답은 ... 거의 항상입니다.

객체에 비 면도 소멸자가 있고 자유롭게 필요한 자식 요소를 추가하도록 하위 클래스가있는 경우 ... 객체 기본 클래스에서 소멸자를 호출하면 자식 요소가 해제되지 않습니다. 이것이 바로 항상 소멸자를 가상으로 선언 해야하는 이유입니다.

우리는 두 개의 공유 라이브러리가 객체를 참조하는 흥미로운 사례가있었습니다. 정의를 변경하여 해방이 필요한 자식 객체를 추가했습니다. 객체 정의가 포함 된 첫 번째 공유 라이브러리를 다시 컴파일했습니다.

그러나 두 번째 공유 라이브러리는 다시 컴파일되지 않았습니다. 이것은 새로 추가 된 가상 객체 정의를 알지 못했음을 의미합니다. Delete는 두 번째 공유 라이브러리에서 호출되었으며 단순히 Free라고 불렀으며 가상 파괴자 체인을 호출하지 않았습니다. 결과는 불쾌한 메모리 누출이었습니다.

다른 팁

예. 하지만 거룩한 담배, 이것에 대해 확신합니까? 그렇다면 나는 사용할 것입니다 놓기 new 당신을 구성합니다 Widget. 배치 사용 new 그리고 명시 적으로 파괴자를 부르는 것은 비정상적인 관용구입니다.

편집하다: 메모리를 사용하지 않고 수동으로 직접 할당하는 것을 고려하십시오. new 첫 번째 객체를 할당 한 다음 나중에 메모리를 재사용합니다. 이를 통해 메모리를 완전히 제어 할 수 있습니다. 예를 들어, 각각에 대해 별도의 메모리 블록을 할당하는 대신 한 번에 큰 덩어리를 할당 할 수 있습니다. Widget. 메모리가 실제로 부족한 자원이라면 그것은 공정한 절약 일 것입니다.

또한, 아마도 더 중요한 것은 배치를하고있을 것입니다. new 이 하이브리드 규칙보다는 "정상적으로" new/놓기 new 해결책. 나는 그것이 효과가 없다고 말하는 것이 아니라, 단지 그것이 다소 다소라고 말하고있다, 아, 창의적인 메모리 문제에 대한 해결책.

그렇습니다. 파괴자는 명시 적으로 부르더라도 하위 주체를 제대로 파괴합니다.

당신이 알고 있듯이, 그것은 드문 행동이지만, 잘 테스트되고 문서화 된 라이브러리의 일부로 유용 할 수 있습니다. 그러나 문서화 (및 프로필)는 유효하고 안전하지만 모든 관리자 (귀하를 포함한)는 결코 편안하게 느끼지 않을 것입니다.

예, 그것은 모든 어린이 소멸자라고 부를 것이므로 예상대로 작동합니다.

파괴자는 결국 기능 일뿐입니다. 삭제됩니다.

그러므로이 접근법을 사용하는 경우 이에주의하십시오.

#include <iostream>

class A
{
public: 
    A(){};
    ~A()
    {
        std::cout << "OMG" << std::endl;
    }
};

int main()
{
    A* a = new A;
    a->~A();
    delete a;
    return 0;
}

output:
OMG
OMG 

삭제자는 실제로 객체에서 삭제가 호출 될 때 두 번째로 불리우므로 파괴자에서 포인터를 삭제하면 0으로 설정해야합니다. 포인터는 아무것도하지 않습니다).

실제 두통을 저장하고 사용하십시오 객체 풀을 부스트하십시오, 소스/싱크 패턴의 기존 구현처럼 들립니다. 그것은 큰 메모리 덩어리를 할당하고, 당신의 객체의 올바른 크기로 자르고 (생성자를 호출 한 후) 당신에게 반환합니다. 객체를 삭제하면 소멸자가 호출되어 재사용 할 링크 된 객체 목록에 넣습니다. 자동으로 성장하고 축소되며 객체의 인스턴스가 메모리에서 서로 가깝게 진행되는지 확인합니다.

다른 것이 없다면, 공부할 수있는 생성자의 새롭고 명백한 사용을 배치하는 좋은 예입니다.

예. 소멸자는 LIFO 순서로 모든 회원 소멸자를 불러서 기본 클래스 소멸자를 부르며 방법이 없습니다. 예방하다 이 소멸자*라고 부르는 것은*입니다. 객체 스택은 풀릴 수 있습니다.

초기화 및 최종화는 C ++의 메모리 할당 및 거래로부터 분리되어 특별한 경우가 발생할 때 애플리케이션 프로그램이 컴파일러에 자신의 의도를 표현할 수있는 명백한 구문이 있습니다.

편집하다:

  • Abort () 또는 longjmp ()를 호출함으로써 실제로 멤버 및 기본 클래스 소멸자가 달리는 것을 막을 수 있다고 생각합니다.

파괴자를 실행하면 파괴되는 물체가 사용하는 메모리를 자유롭게하지 않습니다. 삭제 연산자는 그렇게합니다. 그러나 소멸자가 "하위 물체"를 삭제할 수 있으며 평소에 따라 기억이 해제 될 수 있습니다.

메모리 할당을 제어 할 수 있고 생성자/파괴자가 실행될 때 배치 새/삭제를 읽어야합니다.

작은 정보는 여기를 참조하십시오.

http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.9

STL 컨테이너 가이 작업을 수행합니다. 실제로, STL 할당자는 물체의 파괴자를 호출하는 파괴 방법을 제공해야합니다 (Allcator는 또한 객체를 보유하는 데 사용되는 메모리를 처리하기위한 딜 로이터 방법을 제공합니다). 그러나 Stroustrup의 조언 (C ++ 프로그래밍 언어 10.4.11)입니다

소멸자의 명시 적 요구는 가능한 한 피해야합니다. 때때로, 그들은 필수적입니다. ... 초보자는 파괴자를 명시 적으로 부르기 전에 세 번 생각하고 경험이 많은 동료에게 그렇게하기 전에 물어봐야합니다.

소멸자를 부르는 것은 괜찮습니다. 그러나 당신이 부르는 유형을 조심하십시오. 이 유형에 가상 소멸자가 없으면 (상속하지 않았다) 예상치 못한 동작이 발생할 수 있습니다.

또한 언급 한 바와 같이, 소멸자는 메모리를 자유롭게하지 않지만, 그것이 당신이 처음에 수동으로 부르고 싶은 이유라고 생각합니다.

또한, 내가 착각하지 않는 한, 소멸자를 수동으로 호출하는 것이 생성자를 호출하기 위해 새로운 배치를 사용한 경우 유일한 옵션입니다.

왜 그것을 전혀 파괴합니까? 그냥 메모리를 작성 하시겠습니까? 방출 자원을 우아하게 처리하기 위해 논리를 실행하기를 원하십니까? 나는 이것이 언어의 남용이며 좋은 생각이 아니라는 것을 강조 할 것입니다.

나는 당신이 특별한 할당과 거래 행동을 원하는 객체에 대해 새로운 것을 무시하는 것을 고려할 것입니다. 정상적인 새롭고 명시 적으로 부르는 소멸자의 하이브리드 체계는 미래의 두통을위한 레시피처럼 들립니다. 우선, 모든 메모리 누출 감지 전략이 버릴 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top