문제

나는 foo 객체가 있고 std :: 목록 보유 인스턴스가 있습니다. 내 문제는 목록에 새 인스턴스를 추가 할 때 먼저 CTOR를 호출하지만 DTOR도 호출한다는 것입니다. 그런 다음 다른 인스턴스의 DTOR (이 포인터에 따라).

단일 인스턴스가 목록에 추가되지만 DTOR (부모와 함께) 호출되므로 객체를 예상대로 사용할 수 없습니다.

문제를 설명하기 위해 일부 단순화 된 코드가 있습니다.

#include <iostream>
#include <list>

class Foo
{
public:
    Foo()
    { 
        int breakpoint = 0;
    }
    ~Foo()
    { 
        int breakpoint = 0;
    }
};

int main()
{
    std::list<Foo> li;
    li.push_back(Foo());
}
도움이 되었습니까?

해결책

foo 객체 () 푸시 객체를 push하면 객체가 복사 목록의 내부 데이터 구조로는 다른 인스턴스의 DTOR 및 CTOR가 호출됩니다.

C ++의 모든 표준 STL 컨테이너 유형은 값으로 품목을 가져 가서 필요에 따라 복사합니다. 예를 들어, 벡터가 성장해야 할 때마다 벡터의 모든 값이 복사 될 수 있습니다.

아마 당신은 저장하고 싶을 것입니다 포인터 목록의 개체 대신. 그렇게함으로써 포인터 만 객체 대신 복사됩니다. 그러나 그렇게하면 완료되면 객체를 삭제해야합니다.

for (std::list<Foo*>::iterator it = list.begin(); it != list.end(); ++it) {
    delete *it;
}
list.clear();

또는 Boost 라이브러리와 같은 일종의 '스마트 포인터'클래스를 사용할 수 있습니다.

다른 팁

당신은 여기에 임시 foo를 만들고 있습니다.

li.push_back( Foo() )

푸시 _back은 내부 데이터 구조에 foo를 사본합니다. 푸시 _back이 실행 된 후 임시 Foo가 파괴되어 파괴자라고합니다.

조기 파괴하고 싶지 않은 클래스 멤버에 대한 참조 수를 증가시키는 적절한 사본 생성자가 필요하거나 포인터 솔루션에서 자신을 강제하기 위해 개인적으로 만들 수 있습니다.

이 개체를 사용하여 이해합니다.

class Foo
{
public:
    Foo(int x): m_x(x)
    { 
    std::cout << "Constructed Object: " << m_x << ")\n";
    }
    Foo(Foo const& c): m_x(c.m_x+100)
    {
    std::cout << "Copied Object: " << m_x << ")\n";
    }
    ~Foo()
    {  
    std::cout << "Destroyed Object: " << m_x << ")\n";
    }
};

첫 번째 메인

std::list<Foo*> li;
li.push_back(Foo(1));

여기서 우리는 임시 foo 객체를 만들고 push_back ()을 호출합니다. 임시 객체가 목록에 복사되고 함수가 반환됩니다. 이 진술이 완료되면 임시 대상이 파괴됩니다 (소멸자를 통해). 목록이 파괴되면 포함 된 모든 obejcts도 파괴 할 것입니다 (Foo는 파괴자가있는 대상이므로 파괴자는 소멸자라고 부릅니다).

그래서 당신은 다음과 같은 것을 볼 수 있습니다.

Constructed Object: 1
Constructed Object: 101
DestroyedObject: 1
DestroyedObject: 101

두 번째 예에서는 다음과 같습니다.

std::list<Foo*> li;
li.push_back(new Foo(1));

여기에서 힙에 객체를 동적으로 만듭니다. 그런 다음 푸시 _back ()을 호출하십시오. 여기서 포인터는 목록에 복사됩니다 (포인터에는 생성자/파괴자가 없음). 목록에는 이제 힙의 물체에 대한 포인터가 포함되어 있습니다. 함수가 반환되면 다른 조치가 완료되지 않습니다. 목록이 파괴되면 파괴됩니다 (미묘한 차이가 파괴 및 삭제에 참고) (포인터)가 포함 된 객체 (포인터)는 파괴자가 없으므로 메모리를 누출하지 않습니다.

그래서 당신은 다음과 같은 것을 볼 수 있습니다.

Constructed Object: 1

실제로 여기서 일어나는 것은 당신이 a를 보관한다는 것입니다 복사 목록의 전달 된 개체의 객체는 참조 대신 값으로 전송하기 때문에. 따라서 호출되는 첫 번째 DTOR는 실제로 Push_back 메소드로 전달되는 객체에서 호출되었지만 그때까지 새로운 인스턴스가 생성되었으며 이제 목록에 저장되었습니다.

당신이 사본을 원하지 않는다면 foo 생성 할 객체, 포인터를 저장하십시오 foo 객체 자체 대신 목록의 개체. 물론 그렇게 할 때 목록의 파괴에 대한 메모리를 올바르게 해제해야합니다.

인스턴스 대신 목록을 보유하는 포인터를 만드는 것은 소멸자가 호출되는 문제를 해결합니다. 그러나 나는 여전히 그것이 왜 그런 일이 일어나는지 이해하고 싶습니다.

#include <iostream>
#include <list>

class Foo
{
public:
    Foo()
    { 
        int breakpoint = 0;
    }
    ~Foo()
    { 
        int breakpoint = 0;
    }
};

int main()
{
    std::list<Foo*> li;
    li.push_back(new Foo());
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top