글쓴이 보관물: 소장 마

make_unique와 완벽한 전달 3); 이것은 new멋지게 숨기고 유형을 한 번만 언급합니다. 어쨌든,

std::make_unique표준 C ++ 11 라이브러리에 함수 템플릿 이없는 이유는 무엇 입니까? 나는 찾는다

std::unique_ptr<SomeUserDefinedType> p(new SomeUserDefinedType(1, 2, 3));

조금 장황하다. 다음이 훨씬 좋지 않을까요?

auto p = std::make_unique<SomeUserDefinedType>(1, 2, 3);

이것은 new멋지게 숨기고 유형을 한 번만 언급합니다.

어쨌든, 여기에 구현하려는 나의 시도는 make_unique다음 과 같습니다.

template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

std::forward물건을 컴파일 하는 데 꽤 오랜 시간이 걸렸지 만 그것이 맞는지 확실하지 않습니다. 그렇습니까? 정확히 무엇을 std::forward<Args>(args)...의미합니까? 컴파일러는 무엇을 만드는가?



답변

C ++ 표준화위원회 의장 인 Herb Sutter는 자신의 블로그에 다음 과 같이 썼습니다 .

C ++ 11에 포함되지 않은 make_unique부분은 부분적으로 감독이며 앞으로 확실히 추가 될 것입니다.

또한 OP에서 제공 한 것과 동일한 구현을 제공합니다.

편집 : std::make_unique 이제 C ++ 14의 일부입니다 .


답변

훌륭하지만 Stephan T. Lavavej (더 나은 STL)는에 대한 더 나은 솔루션을 제공하며 make_unique, 이는 어레이 버전에서 올바르게 작동합니다.

#include <memory>
#include <type_traits>
#include <utility>

template <typename T, typename... Args>
std::unique_ptr<T> make_unique_helper(std::false_type, Args&&... args) {
  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

template <typename T, typename... Args>
std::unique_ptr<T> make_unique_helper(std::true_type, Args&&... args) {
   static_assert(std::extent<T>::value == 0,
       "make_unique<T[N]>() is forbidden, please use make_unique<T[]>().");

   typedef typename std::remove_extent<T>::type U;
   return std::unique_ptr<T>(new U[sizeof...(Args)]{std::forward<Args>(args)...});
}

template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
   return make_unique_helper<T>(std::is_array<T>(), std::forward<Args>(args)...);
}

이것은 그의 핵심 C ++ 6 비디오 에서 볼 수 있습니다 .

make_unique의 STL 버전의 업데이트 된 버전으로 사용할 수 있습니다 N3656 . 이 버전 초안 C ++ 14에 채택 되었습니다.


답변

std::make_shared에 대한 속기 만이 아닙니다 std::shared_ptr<Type> ptr(new Type(...));. 그것 없이는 할 수없는 일을합니다.

작업을 수행 std::shared_ptr하려면 실제 포인터의 스토리지를 보유하는 것 외에도 추적 블록을 할당해야합니다. 그러나 std::make_shared실제 객체를 할당 하기 때문에 동일한 메모리 블록에 std::make_shared객체 추적 블록을 모두 할당 할 수 있습니다 .

따라서 std::shared_ptr<Type> ptr = new Type(...);두 개의 메모리 할당 ( 트래킹 블록의 new하나에 대한 하나 std::shared_ptr) std::make_shared<Type>(...)하나 의 메모리 블록을 할당 합니다.

이는의 많은 잠재 사용자에게 중요합니다 std::shared_ptr. a std::make_unique가 할 수 있는 유일한 것은 약간 더 편리합니다. 그 이상은 없습니다.


답변

아무것도 당신이 당신의 자신의 도우미를 작성하는 것을 막을 수는 없지만 make_shared<T>, 라이브러리에서 제공하는 주된 이유 는 실제로 shared_ptr<T>(new T)다른 할당 된 공유 포인터 유형을 생성하기 때문 입니다. 돕는 사람.

귀하 make_unique반면에 래퍼는 주변 단순한 문법 설탕이다 new가, 그것은 아무것도 가져 오지 않는 눈에 기쁘게을 보일 수 있도록하면서, 표현 new테이블에 있습니다. 수정 : 이것은 사실이 아닙니다. new표현식 을 감싸기 위해 함수 호출을 하면 예외 안전을 제공합니다 (예 : 함수를 호출하는 경우) void f(std::unique_ptr<A> &&, std::unique_ptr<B> &&). new서로에 대해 순서가 다른 두 개의 raw를 갖는 것은 하나의 새로운 표현식이 예외로 실패하면 다른 하나는 자원을 누출시킬 수 있음을 의미합니다. make_unique표준에 없는 이유에 관해서는 : 그것은 잊혀졌습니다. (이것은 때때로 발생합니다. 글로벌도 없습니다.std::cbegin 표준에 이 없어도 표준 .)

또한 unique_ptr두 번째 템플릿 매개 변수를 사용하여 어떻게 든 허용해야합니다. 이것은 shared_ptr유형 삭제를 사용하여 저장 하는와 다릅니다. 사용자 정의 기를 유형의 일부로 만들지 않고 하는 것과 다릅니다.


답변

C ++ 11에서는 ...“팩 확장”에도 템플릿 코드로 사용됩니다.

요구 사항은 확장되지 않은 매개 변수 팩을 포함하는 표현식의 접미사로 사용하고 팩의 각 요소에 표현식을 적용하는 것입니다.

예를 들어, 귀하의 예를 바탕으로 :

std::forward<Args>(args)... -> std::forward<int>(1), std::forward<int>(2),
                                                     std::forward<int>(3)

std::forward<Args...>(args...) -> std::forward<int, int, int>(1,2,3)

후자는 틀렸다고 생각합니다.

또한 인수 팩은 확장되지 않은 함수로 전달되지 않을 수 있습니다. 템플릿 매개 변수 팩이 확실하지 않습니다.


답변

스테판 T. Lavavej에 의해 구현에 의해 영감을, 나는 배열 범위를 지원되는 make_unique이 좋을 거라 생각 은 GitHub의에이야 그리고 난에 대한 의견을 얻을 싶어요. 이를 통해 다음을 수행 할 수 있습니다.

// create unique_ptr to an array of 100 integers
auto a = make_unique<int[100]>();

// create a unique_ptr to an array of 100 integers and
// set the first three elements to 1,2,3
auto b = make_unique<int[100]>(1,2,3); 

답변