표준 컨테이너와 함께 std :: auto_ptr <>을 사용하는 것이 왜 잘못 되었습니까?


217

std::auto_ptr<>표준 용기와 함께 사용 하는 것이 왜 잘못 되었습니까?


5
많은 사람들이 이것을 잘못 본 것을 보았 기 때문에 분명히 +1입니다. 물어 보는 것은 좋은 질문입니다.
twokats

관련 항목도 읽으십시오. 이 질문은 다른 쪽에서 여기에서 고려됩니다. auto_ptr 및 STL 컨테이너에 대한 자세한 내용을 이해하는 데 도움이 될 수 있습니다. stackoverflow.com/questions/8630552/…
nickolay


1
move시맨틱하고 unique_ptr관련 문제를 피하도록 설계되었습니다 auto_ptr. C ++ 03에서 언어는 auto_ptr컴파일러와 언어가 l과 r 값을 구분할 수 없었기 때문에 원하는 동작을 얻기 위해 일부 "해킹"이 사용 되었기 때문에 모든 시나리오에서 정확하고 안전하게 동작 하는 클래스를 작성할만큼 강력 하지 않았습니다. 대부분의 시간.
Phil1970

멋진 기사 : STL 컨테이너와 Auto_ptrs은 - 왜 그들은 혼합하지 마십시오 quantstart.com/articles/...을
alfC

답변:


124

C ++ 표준에 따르면 STL 요소는 "복사 가능"및 "할당 가능"해야합니다. 즉, 요소를 할당하거나 복사 할 수 있어야하며 두 요소는 논리적으로 독립적입니다. std::auto_ptr이 요구 사항을 충족하지 않습니다.

이 코드를 예로 들어 보겠습니다.

class X
{
};

std::vector<std::auto_ptr<X> > vecX;
vecX.push_back(new X);

std::auto_ptr<X> pX = vecX[0];  // vecX[0] is assigned NULL.

이 제한을 극복하려면 C ++ 11이없는 경우 std::unique_ptr, std::shared_ptr또는 std::weak_ptr스마트 포인터 또는 부스트 기능을 사용해야합니다. 이러한 스마트 포인터에 대한 부스트 라이브러리 설명서는 다음과 같습니다.


7
공유 소유권이 필요하지 않은 경우 부스트 포인터 컨테이너도 고려해야합니다.
me22

4
unique_ptr또한 복사를 허용하지 않기 때문에 특정 STL 작업은 이동 의미를 사용할 수 없으면 제대로 작동하지 않습니다.
Mike Weller

4
"이 제한을 극복하려면 std::unique_ptr": 해당 클래스 템플리트는 이동 의미론 (사양에 rvalue 참조가 필요함) 때문에 존재할 수 있으므로 기본적으로 C ++ 11이 필요합니다. 그러나 C ++ 11 표준은 더 이상 STL 요소 유형이 "복사 가능"및 "지정 가능"해야한다고 말하지 않습니다. 이동 구성 가능 및 이동 할당 가능 실제로 unique_ptr인스턴스는 이동 구성 및 이동 할당 만 가능합니다. 그러나 auto_ptr인스턴스도 마찬가지입니다 ! 결과적으로 C ++ 11에서는 할 수있는 auto_ptr일을 할 수 있습니다 unique_ptr.
Marc van Leeuwen

당신이하지 않는 @MarcvanLeeuwen resetrelease필요에 따라
래칫 괴물

2
@ratchetfreak : 흠, 이해가 안 돼요. 뭐? "당신 reset과 "가 아니라면 release, 그것이 내 의견에 어떤 것이 적용되는지는 알 수 없습니다. 모두 참고 auto_ptr하고 unique_ptr이 두 가지 방법이 있고, 그들은 두 경우 모두 같은 일을한다.
Marc van Leeuwen

66

복사 의미 의이 auto_ptr컨테이너와 호환되지 않습니다.

특히, 하나 auto_ptr를 다른 것으로 복사 해도 하나의 포인터 소유권을 잃어 버리므로 두 개의 동일한 객체가 만들어지지 않습니다.

보다 구체적으로, 복사 auto_ptr하면 복사본 중 하나가 포인터에서 벗어날 수 있습니다. 컨테이너에 남아있는 것은 정의되어 있지 않습니다. 따라서 auto_ptrs컨테이너에 저장하면 포인터에 임의로 액세스 할 수 없게됩니다 .


39

주제에 관한 두 가지 훌륭한 기사 :


나는 거의 2 년에 걸쳐서 그 문제를 다룰 것이라고 생각하기 때문이다.
강아지

27
@DeadMG : 예, 맞습니다. 그러나 그것은 나의 목적이 아니었다. 누군가이 스레드에 언젠가 와서 배우고 auto_ptr물건 을 배우고 싶다면 이 링크가 도움이 될 것입니다.
Lazer

최신 복제본이 많이 있습니다.
강아지

8
@DeadMG :이 질문은 중복 된 것으로 닫히지 않았으므로 확장 가능합니다. Lazer는 여기서 전에 말하지 않은 것을 말했다. 그가 우연히 온 것 같아
Sebastian Mach

을 호출 한 후 문제를 분석하는 두 번째 링크의 설명은 sort()여기에있는 모든 답변보다 명확합니다.
chaosink

17

STL 컨테이너는 저장 한 항목을 복사 할 수 있어야하며 원본과 복사본이 동일 할 것으로 예상됩니다. 자동 포인터 객체는 계약이 완전히 다르므로 복사하면 소유권 이전이 생성됩니다. 즉, auto_ptr의 컨테이너는 사용법에 따라 이상한 동작을 나타냅니다.

Effective STL (Scott Meyers) 항목 8에서 잘못 될 수있는 사항에 대한 자세한 설명과 Effective C ++ (Scott Meyers) 항목 13에서 자세히 설명하지 않습니다.


12

STL 컨테이너는 포함 된 항목의 사본을 저장합니다. auto_ptr을 복사하면 이전 ptr이 널로 설정됩니다. 이 동작으로 인해 많은 컨테이너 메서드가 손상되었습니다.


그러나 unique_ptr을 사용할 때 단 하나의 unique_ptr 만 객체의 소유권을 가질 수 있기 때문에 거의 같은 결과를 얻습니다.
Tracer

2
unique_ptr적절한 C ++ 11 객체와 같은 @Tracer 는 이동 구성 또는 할당시에만 리소스 소유권을 이전 할 수 있으므로 프로그래머는 lvalue를std::move(sourceObject) 전달하고 의도 하지 않게 / 예측할 ​​수없는 방식으로 변경하지 않고 의도적으로 또는 임시를 전달해야합니다. 여기에서 철저히 강조한 것처럼 복사 할당은의 핵심 문제였습니다 . auto_ptr
underscore_d

4

C ++ 03 표준 (ISO-IEC 14882-2003) 은 20.4.5 단락 3에서 말합니다 :

[...] [ 참고 : [...] auto_ptr은 표준 라이브러리 컨테이너 요소에 대한 CopyConstructible 및 Assignable 요구 사항을 충족하지 않으므로 auto_ptr로 표준 라이브러리 컨테이너를 인스턴스화하면 정의되지 않은 동작이 발생합니다. — 끝 참고 ]

C ++ 11 표준 (ISO-IEC 14882-2011) 은 부록 D.10.1 단락 3에서 말합니다 :

[...] 참고 : [...] auto_ptr 인스턴스는 MoveConstructible 및 MoveAssignable의 요구 사항을 충족하지만 CopyConstructible 및 CopyAssignable의 요구 사항은 충족하지 않습니다. — 끝 참고]

부록 C.4.2 부록 D : C ++ 14 표준 (ISO-IEC 14882-2014)에 호환성 기능이 나와 있습니다.

변경 : 클래스 템플릿 auto_ptr, unary_function 및 binary_function, 함수 템플릿 random_shuffle 및 함수 템플릿 (및 반환 유형) ptr_fun, mem_fun, mem_fun_ref, bind1st 및 bind2nd는 정의되지 않습니다.
이론적 근거 : 새로운 기능으로 대체되었습니다.
원래 기능에 미치는 영향 :이 클래스 템플릿과 함수 템플릿을 사용하는 유효한 C ++ 2014 코드는이 국제 표준에서 컴파일되지 않을 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.