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);