2010-01-04 5 views
12

std::queue은 스레드 안전 큐를 만들기 위해 템플릿 기반 클래스로 래핑됩니다. 이 클래스에는 두 가지 버전이 있습니다. 하나는 값 유형을 저장하는 버전이고 다른 하나는 포인터 유형을 저장하는 버전입니다.C++ std :: queue :: pop()은 소멸자를 호출합니다. 포인터 유형은 무엇입니까?

포인터 유형의 경우 삭제시 대기열 요소를 삭제하는 데 문제가 있습니다. 그 이유는 항목을 안전하게 큐에서 제거하는 방법을 모르기 때문입니다.

This 대기 상태에서 요소를 제거하는 유일한 방법은 pop()을 호출하는 것입니다 (공백 상태이므로 실제로는 상태가 아닙니다). 참조는 또한 pop()이 항목에 대한 소멸자를 호출한다고 말합니다.

글쎄, 포인터가 실제로 집계를 가리킬 수도 있고 그렇지 않을 수도 있기 때문에 포인터 유형에 문제가 발생합니다. 그것들 중 하나가 집합체를 가리키면 모두 그렇지만 래퍼가 템플리트 화되어 있기 때문에 어떤 유형 (집합체 또는 집합체가 아닌)을 다루고 있는지 보장 할 수 없습니다.

따라서 pop()이 소멸자를 호출하면 어떻게됩니까? 어떻게하면 모든 것이 제거되고 메모리 할당 해제가 제대로 이루어 지도록 할 수 있습니까?

마지막으로, 제 솔루션은 ARM9 용 GCC의 이전 버전을 사용하고 있습니다. 나는 이것에 대한 통제권이 없다. 나는 여기에 도움이 될 스마트 포인터와 컨테이너가있는 라이브러리가 있다는 것을 이해하지만, 그들은 나를 위해 출입 제한이 있습니다.

+0

"실제로 포인터가 집계를 가리킬 수도 있고 그렇지 않을 수도 있기 때문에 포인터 유형에 문제가 발생합니다."집계가 여기서 무엇을해야 하는지를 이해하지 못합니다. –

답변

13

온라인 소스는 귀하가 지불하는 가치가 있습니다. Josuttis's book과 같은 적절한 참조를 얻으십시오. pop()은 "destructor를 호출하지 않습니다"- pop_front()를 호출하여 대기열 어댑터의 기본 표현 (기본적으로 std :: deque)에서 요소를 간단히 제거합니다. 만약 pop 된 객체가 소멸자를 가지면, pop 된 객체가 범위를 벗어날 때 사용되지만 큐 클래스는 그 객체와 아무 상관이 없습니다.

+0

Thx 명확히하기 위해, 나는 그 성명 주위에 머리를 감싸는 데 어려움이있었습니다 : "이것은 제거 된 엘리먼트의 소멸자를 호출합니다" –

+0

팝업 된 객체가 어떤 형태의 스마트 포인터에 삽입되었다고 가정합니다. –

+0

정보 및 도서 링크를 제공해 주셔서 감사합니다. –

30

포인터 자신이에 실제로는 소멸자가 없으므로 포인터가 포함 된 대기열에서 pop()을 호출하면 포인터가 가리키는 객체의 소멸자가 호출되지 않습니다.

+0

답변 해 주셔서 감사합니다.이것은 내 궁금증에 대한 질문에서 분명하지 않다면 내가 궁금해 한 것입니다. –

+0

그렉, 나는 빠른 답변을 고맙게 생각하고 여전히 투표를하고 있지만, 어떤 일이 일어나고 있는지 좀 더 철저히 설명하고 있기 때문에 Neil의 답변을 받아 들였습니다. –

+0

동의합니다. 사고의 라인은 매우 좋지만 : D. 첫 번째 표지판은 포인터에 소멸자가 없어야합니다. –

1

"모든 것을 제거하고 메모리 할당을 올바르게 제거하려면 어떻게합니까?" 당신이 절대적으로 당신의 큐에서 포인터를 저장해야하고, 당신은 그들이 포인터의 큐 대신 다음, pop 에드있을 때이를 자동으로 해제하려면

, 당신은 포인터를 저장하는 객체의 대기열을해야하고, 소멸자에서 삭제하십시오. 예를 들어 shared_ptr의 대기열을 사용할 수 있습니다. shared_ptr은 표준 라이브러리에 없지만 TR1의 일부이며 널리 사용 가능합니다.

그렇지 않으면 개체를 삭제하는 호출자의 책임 :

T *off = q.front(); 
q.pop(); 
delete off; 

요약은 포인터의 컨테이너 동적 오브젝트가 조금 어색 할당하는 것입니다. 컨테이너가 동적 객체에 대한 포인터 대신 객체의 복사본을 저장하도록 프로그램을 설계 할 수 있다면 그렇게하십시오. 그렇지 않으면 컨테이너가 아닌 리소스 소유권을 담당하게됩니다. STL 컨테이너는 소유권에 대해 아무 것도 모른다. 그들은 단지 value_type을 복사하고 파괴한다. 포인터를 복사하고 파기하는 것은 포인터가 가리키는 대상에는 아무런 영향을 미치지 않습니다.

+0

나는 이것에 대해 생각했지만 템플릿 클래스의 미래 사용법을 알지 못하기 때문에 그것을 거부했다. 스레드 안전 문제에 대한 사용자 b/c에 대한 큐에 원시 액세스를 제공하지 않으려는데, 사용자가 방금 언급 한 아이디어를 사용할 것이라고 보장 할 수 없으므로 이에 대해 결정했습니다. –

+0

클래스가 숨겨진 큐의 값 유형으로 템플릿 매개 변수를 사용하는 경우 컨테이너가 수행하는 작업을 수행해야합니다. 사용자가 아무 것도 할당하지 않으면 사용자는 결국이를 해제해야합니다 (예 : 스마트 포인터를 값 유형으로 사용). 예를 들어, 이벤트 대기열이고 사용자가 일반 포인터를 사용하려고한다면 이벤트 핸들러에서 객체를 해제 할 수 있습니다. 하지만 그것은 컨테이너의 문제가 아니며, IMO는 포인터를 특별히 처리하는 컨테이너를 작성해서는 안됩니다. –

+0

... 분명히, 이것은 단지 다음 사람에게 문제를 던져 버릴뿐입니다. 그러나 컨테이너를 소유권과 혼동하지 않는 데는 좋은 이유가 있습니다. 정적 인 데이터 또는 무언가를 가리 키기 때문에 소유권을 부여하지 않고 누군가가 컨테이너를 사용하여 포인터를 저장하려고 할 수 있습니다. boost :: ptr_deque는 대기열의 기본 컨테이너로 사용할 수 있으므로 대기열과 같은 두 개의 템플릿 매개 변수를 가질 수 있으므로 사용자가 원하는 경우 해당 매개 변수를 사용할 수 있습니다. –

관련 문제