2012-01-24 1 views
6

나는 unique_ptr의 벡터를 내가 만들고있는 클래스의 멤버로 갖고 싶습니다.unique_ptr의 벡터를 클래스 데이터 멤버로 선언하는 방법은 무엇입니까?

class Foo { 
    [...] 

private: 
    vector<unique_ptr<Bar>> barList; 
} 

그러나 나는 VS2010 컴파일러에서 암호 같은 오류 메시지를 받기 시작 : std::_Copy_impl<>의 마이크로 소프트의 구현에 뛰어 아래에서 에러 라인의 소수와 함께

error C2248: 'std::unique_ptr<_Ty>::operator =' : cannot access private member declared in class 'std::unique_ptr<_Ty>' 

...

회원 선언을

vector<unique_ptr<Bar>>* barList; 
로 변경했습니다.

그리고 컴파일됩니다. 그러나 내가 원했던 방식으로 왜 그것을 할 수 없는지 궁금하지 않을 수 없다. 싱긋 웃음을 위해, 나는이 시도하고 그것을 잘 작동합니다 :

vector<Bar> barList; 

하지만 지금은 unique_ptr의 편의를 잃게됩니다. 나는 나의 케이크를 원하고 나는 그것을 역시 먹고 싶다!

+0

나는 http://stackoverflow.com/questions/8553464/vector-as-a-class-member를보고 있었고 그 대답은 내가했던 것처럼 '벡터'선언을한다고 생각하는 것처럼 보인다. 그러나 어떤 이유로 인해 'unique_ptr'부분을 추가 할 때 불법 복제가 시작되는 것으로 보입니다. –

+1

복사 생성자와 할당 연산자는 어떻게 생겼습니까? –

+0

개인 지정이지만 복사 생성자가 범인입니다. 잘못된 소유권 의미론을 사용하고 있음을 깨달았을 때'unique_ptr'에서'shared_ptr'로 변경되었습니다. –

답변

10

여기서 문제는 어딘가에서 코드가 Foo의 "copy-assignment"연산자를 호출하려고한다는 것입니다.

이렇게하면 컴파일러가 모든 하위 개체 Foo의 복사 할당 연산자를 호출하는 복사 할당 연산자를 생성합니다. 결국 이것은 unique_ptr을 복사하려는 시도로 이어지며 불가능한 작업입니다.

+0

이것을 지적 해 주셔서 감사합니다. 컴파일러는 오류가 멤버 선언을 참조하고 복사본을 만드는 잘못된 코드에 대해 언급하지 않았기 때문에 저를 오도했습니다. 나는 이것이 VS2010의 결함이라고 상상하고 새로운 릴리즈로 개선되기를 희망합니다. 내'Foo' 클래스에는 복사 생성자가 있으며 원본 'Foo'에서 벡터를 복사하려고했습니다. 공유 소유권이 더 나은 해결책 인 것 같아서'shared_ptr '로 전환하는 것이 트릭을 만들었습니다. –

+1

VS2010의 버그처럼 보입니다. 코드가 copy-assigment를 호출하지 않아도이 오류가 발생합니다. 비공개로 선언하여 연산자 =를 비활성화하면 (따라서 = 삭제가 지원되지 않음) 문제가 해결됩니다. – tr3w

-2

vector 구현은 값 할당 연산자에 따라 달라 지므로 unique_ptr을 벡터에서 사용할 수 없습니다.이 연산자는 unique_ptr에서 private입니다. 부스트 또는 C++ 11의 다른 스마트 ptr 구현의 shared_ptr을 사용하십시오.

+6

'unique_ptr'은'vector'에서 잘 동작합니다. –

+0

C++ 11 컨테이너는'unique_ptr'과 같은 이동 전용 타입으로 작업해야합니다. [참고.] (http://ideone.com/riLhp) – bames53

+0

나는 그가 그것을 사용하는 방법을 의미. 하지만 여전히 감사합니다, 나는 emplace_back에 대해 몰랐습니다. – aambrozkiewicz

4

unique_ptr에는 복사 의미가 없으므로 포함 된 개체를 복사 할 수있는 방법을 사용할 수 없습니다. 수 있습니다 복사 할 곳에서 std::move 사용하여 rvalue 참조가이 작업을 수행하십시오. 귀하의 코드를 보지 않고 나는 그것이 어디 있는지 말할 수 없습니다.

두 번째 형식으로 컴파일하는 경우 동일한 코드를 사용하지 않았거나 컴파일러 버그가 있습니다. 둘 다 같은 방식으로 실패해야합니다.

값으로 저장하는 세 번째 예제는 값으로 저장/복사하는 데 비용이 많이 드는 개체가 크지 않고 가장 간단한 방법입니다.

+1

'auto_ptr'은 일반적인 복사 의미를 따르지 않는 것이고,'unique_ptr'은 ** 복사 의미를 가지고 있지 않습니다. – Grizzly

+0

당신의 것과 Mankarse의 대답은 매우 비슷합니다. 그러나 그분은 제가 마녀가 불쾌한 코드를 찾으러 갈 필요가 있다는 것을 깨닫게했습니다. 그래도 둘 다 받아 들여진 대답을받을 자격이있어. 도와 주셔서 감사합니다! –

2

흔히 std::move(iUniquePtr)이 어딘가에 누락되어있다 (예를 들어, push_back을 사용할 때). 에서

0

발췌 www.cplusplus.com unique_ptr 할당 개체가 개체를 삭제하는 책임과 함께 저장된 포인터와 저장 Deleter가 (모두 포함 X의 내용의 소유권을 획득

std::unique_ptr::operator= 

어떤 시점에서). 호출 전에 unique_ptr 객체가 소유 한 모든 객체가 삭제됩니다 (unique_ptr의 소멸자가 호출 된 것처럼).

그러나 너무 경고가 :

이 페이지는 C++ 표준 (2011)의 최신 개정에 의해 도입 된 기능에 대해 설명가. 구형 컴파일러는 지원하지 않을 수 있습니다.

MSVC 2010은 operator=을 비공개 (복사 불가능)로 정의하지만 swap 메서드를 지원합니다.

관련 문제