2014-09-29 9 views
3

에 새 개체를 추가하는 방법을 이해할 수 없습니다. unique_ptr의 std :: list에 이상한 문제가 있습니다.std :: list <std :: unique_ptr <classname>>

클래스 slFlyingMonster는 클래스 slMonster에서 파생되었습니다.

다음 코드는 작동 :

std::unique_ptr<slMonster> ptr(new slFlyingMonster(md)); 

그러나이 코드 :

std::list<std::unique_ptr<slMonster>> mMonsters; 
mMonsters.push_back(new slFlyingMonster(md)); 

오류 발생을 :

"Error 1 error C2664: 'void
std::list>,std::allocator>>>::push_back(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' : cannot convert argument 1 from 'slFlyingMonster *' to 'std::unique_ptr> &&'"

나는 이해하지만, 뭔가 표준 : : 목록과 같은 잘못이다 .push_back()은 =와 같지 않지만 새 클래스를 unique_ptr로 올바르게 추가하는 방법을 알아낼 수 없습니다. 어떤 제안이라도 대환영입니다.

답변

4

목록에 포함 된 유형의 개체가 있고 해당 복사본을 밀어 넣을 때 push_back을 사용하십시오. 그러나

std::list<std::unique_ptr<slMonster>> mMonsters; 
mMonsters.emplace_back(new slFlyingMonster(md)); 

: 아직 그러한 객체가없는 경우 일반적으로 (귀하의 경우, 당신은하지 않음) 대신 emplace_back를 사용하여 목록 —에 직접 새 개체를 초기화하는 것이 더 낫다 @SebastianRedl이 주석에서 올바르게 지적했듯이, 위의 예외는 안전하지 않은 문제가 있습니다. std::list 안에 새 노드의 내부 할당이 throw되면 새 slFlyingMonster 인스턴스가 유출됩니다. 인수 중 하나가 보호되지 않은 리소스 (예 : 메모리 소유 마우스 포인터) 인 경우 emplace_back은 올바른 선택이 아닙니다.

그래서 실제로 래퍼 스마트 포인터를 구성하여 목록에 넣기를 원합니다. C++ 14에서는, 당신은 std::make_unique하여이 작업을 수행 할 수 있습니다 : 일반 C++ (11)와

std::list<std::unique_ptr<slMonster>> mMonsters; 
mMonsters.push_back(std::make_unique<slFlyingMonster>(md)); 

을, 당신은 당신의 자신의 make_unique 구현, 또는 명시 적으로 스마트 포인터 만들 수 있습니다 :

std::list<std::unique_ptr<slMonster>> mMonsters; 
mMonsters.emplace_back(std::unique_ptr<slMonster>(new slFlyingMonster(md))); 
+0

'mMonsters.push_back ({new slFlyingMonster (md)});는 컴파일되지 않습니다. 그 생성자는'explicit'입니다. –

+0

@ T.C. 고마워요. 인상 목록 아래에있었습니다. 초기화는 명시 적 생성자를 허용했습니다. 나는 고쳤다 – Angew

+1

이것은 예외 안전하지 않다. 'list'는 요소를 생성하기 전에 새로운 노드를 할당해야하며,이 경우 throw 될 수 있습니다.이 경우 새로 할당 된 객체가 유출됩니다. –

4

당신은 emplace_back 사용할 수 있습니다 :

std::list<std::unique_ptr<slMonster>> mMonsters; 
mMonsters.emplace_back(new slFlyingMonster(md)); 

또는이와 push_back std::make_unique :

std::list<std::unique_ptr<slMonster>> mMonsters; 
mMonsters.push_back(std::make_unique<slFlyingMonster>(md)); 

또는 std::unique_ptr<T>(T*) 명시 적 인 std::unique_ptr

std::list<std::unique_ptr<slMonster>> mMonsters; 
std::unique_ptr<slMonster> p(new slFlyingMonster(md)); 
mMonsters.push_back(std::move(p)); 

생성자의 std::move, 그래서 T* 암시 적으로 std::unique_ptr을 생성 할 수 없습니다.

+0

그것은 것을 'emplace_back (T && ...)'와'push_back (T &&)'의 차이점에 대해서도 설명했다면 더 좋을 것입니다. –

+0

'push_back (make_unique ...)'이 최선의 해결책입니다. 첫 번째 예외는 예외가 아닙니다. 세 번째는 개체 생성과 추가 사이에 더 많은 작업을하지 않는 한 지나치게 길다는 것입니다. –

관련 문제