2010-06-01 15 views
52

부스트 라이브러리에 C++ 1x의 std :: unique_ptr에 해당하는 클래스가 있습니까? 내가 지금처럼 예외 안전 공장 기능을 수있게되고 찾고 있어요 행동 ...unique_ptr 부스트가 이에 해당합니까?

std::unique_ptr<Base> create_base() 
{ 
    return std::unique_ptr<Base>(new Derived); 
} 

void some_other_function() 
{ 
    std::unique_ptr<Base> b = create_base(); 

    // Do some stuff with b that may or may not throw an exception... 

    // Now b is destructed automagically. 
} 

편집 : 지금, 나는 내가 할 수있는 가장 좋은 것 같아이 해킹을 사용하고 있습니다 ...이 시점에서 interprocess 라이브러리에서

Base* create_base() 
{ 
    return new Derived; 
} 

void some_other_function() 
{ 
    boost::scoped_ptr<Base> b = create_base(); 

    // Do some stuff with b that may or may not throw an exception... 

    // Now b is deleted automagically. 
} 
+0

또한이 효과는 복사 생성자에 이동 의미 체계를 만들어서 생성 한 다음 소멸자가 해제하기 전에 검사 할 수 있습니까? –

답변

64

unique_ptr없이 C++ 0x (표준 라이브러리에 포함되어 있으므로 Boost에서 제공하지 않아도 됨)를 만들 수 없습니다.

C++ 0x의 기능인 rvalue 참조가 없으면 Boost를 포함하거나 포함하지 않고 unique_ptr의 강력한 구현이 불가능합니다.

C++ 03에는 각각 결함이 있지만 몇 가지 가능한 대안이 있습니다.

  • boost::shared_ptr은 아마도 capabilites의 관점에서 가장 간단한 대체품 일 것입니다. unique_ptr을 사용하면 어디에서나 안전하게 사용할 수 있으며 제대로 작동합니다. 추가 된 참조 계산 때문에 효율성이 떨어집니다. 그러나 당신이 할 수있는 모든 것을 다룰 수있는 간단한 드롭 인 교체를 찾고 있다면, 아마도 이것이 최선의 방법 일 것입니다. 물론 shared_ptr도 훨씬 더 많은 작업을 수행 할 수 있지만 unique_ptr의 드롭 인 대체품으로 사용할 수도 있습니다.
  • boost::scoped_ptrunique_ptr과 유사하지만 소유권 이전을 허용하지 않습니다. 똑똑한 포인터가 평생 동안 독점적 인 소유권을 유지하기위한 것이라는 점은 훌륭합니다.
  • std::auto_ptrunique_ptr과 매우 유사하지만 몇 가지 제한 사항이 있습니다. 주로 표준 라이브러리 컨테이너에 저장할 수 없습니다. 소유권 이전을 허용하는 포인터를 찾고 있지만 컨테이너에 저장하거나 주위에 복사 할 수없는 포인터를 찾고 있다면이 방법이 좋습니다.
+4

+1'auto_ptr'에 대해서 - 왜냐하면'unique_ptr'은 [auto_ptr이 버그를 일으키는 곳]에서 컴파일되지 않기 때문입니다. (http://stackoverflow.com/questions/111478/why-is-it-wrong-to-use-stdauto -ptr-with-stl-containers), 이것은 정확히 OP가 찾고자하는 것입니다. –

+4

하워드 Hinnant의 unique_ptr for C++ 03은 r-value refs가 존재하지 않는다는 것을 고려하면 꽤 잘 작동합니다. –

+0

Howard Hinnant가 Boost에서 이미 검토 한 이동 의미론 에뮬레이션을 사용하여 시연했듯이 이는 완전히 사실이 아닙니다. 누군가가 그 구현을 취하여 곧 부스트에 포함하기를 바랍니다. –

5

방법에 대한 unique_ptr을 얻을?

+0

함수에서 안전하게 반환 할 수 있습니까? 나는 그것에 관해 아무것도 발견 할 수 없었다 (그러나 어쩌면 나는 단지 장님이다). 또한 스마트 포인터 라이브러리 대신 프로세스 라이브러리에 있다는 점을 감안할 때 "사용"하는 것이 올바른 것입니까? –

+0

@wowus : 아니요. C++ 0x에서 새로 추가 된 이동 의미론에 의존합니다. 부스트로 간단히 에뮬레이션 될 수는 없지만 그 기능은 컴파일러 자체에 존재해야합니다. –

+0

그냥 보니 r 값 참조가 필요합니다. 그러므로, 내가 찾는 것이 아닙니다. –

10

당신은 C++ 03 하워드 Hinnant의 '개념의 증명'unique_ptr<> 구현을 시도 할 수도 있습니다 (면책 조항 - 내가하지 않은)의

한 그의 예는 unique_ptr<int> 반환 :

unique_ptr<int> factory(int i) 
{ 
    return unique_ptr<int>(new int(i)); 
} 
+0

프로덕션 코드에서이 코드를 사용했지만 꽤 잘 작동합니다. 우리가 가진 유일한 문제는'boost :: make_shared'를'unique_ptr' 매개 변수를 가진'class'에 대해 호출하는 것입니다. –

4

나는 하워드 Hinnant의 012을 사용했습니다. 컴파일러에서 미친 메타 프로그래밍 오류를 읽는 데 정말로 능숙하지 않은 경우 명확하게 조정할 수 있습니다. 그러나이 경우의 90 %에서 unique_ptr처럼 작동합니다.

그렇지 않으면 매개 변수를 boost::scoped_ptr&으로 전달하고 내부적으로 스왑하여 소유권을 훔칠 것을 제안합니다. unique_ptr 스타일 반환 값을 얻으려면 auto_ptr을 사용하십시오. auto_ptr 반환 값을 shared_ptr 또는 scoped_ptr으로 캡처하여 auto_ptr을 직접 사용하지 않는 것이 좋습니다.

33

Boost 1.57에서 시작하여 Boost.Move 라이브러리에는 공식 unique_ptr이 구현되어 있습니다. documentation에서

:

(...) C++ 03 컴파일러에서도 사용 가능한 표준 :: unique_ptr을위한 드롭 인 교체.

코드는 <boost/move/unique_ptr.hpp> 헤더 파일에서 사용할 수 있으며 boost::movelib 네임 스페이스에 있습니다. 또한 Boost.Move 라이브러리는 <boost/move/make_unique.hpp>make_unique() 팩토리 기능을 제공하며 boost::movelib 네임 스페이스에도 있습니다.

#include <boost/move/unique_ptr.hpp> 

using boost::movelib::unique_ptr; 

unique_ptr<Base> create_base() 
{ 
    return unique_ptr<Base>(new Derived); 
} 

a live example on Wandbox를 참조하십시오

따라서 질문의 예는 이러한 방식으로 구현 될 수있다. 이 코드는 gcc 4.6.4에서 C++ 98 모드 (!)로 잘 컴파일됩니다.

boost::movelib::unique_ptr에서 흥미로운 점은 기본/파생 클래스를 사용하여 사례에 적용 할 때 구현시 기본 클래스의 가상 소멸자 선언에 대한 컴파일 타임 검사를 제공합니다. the code won't compile을 생략하면 ("실행 (...)"버튼을 클릭하면 컴파일러 오류 메시지가 표시됩니다).

하나의 사소한 문제는 boost/move 디렉토리에서 오는 것이지만 코드는 boost::movelib 네임 스페이스 (미묘한 차이이지만 성가시다 수 있음)에 있습니다.

자세한 내용은 a thread on boost mailing list도 참조하십시오.

이 유일하고 유용한 코드는 Ion Gaztañaga에게 감사드립니다.

관련 문제