std::unique_ptr
예를 들어 배열을 지원합니다.
std::unique_ptr<int[]> p(new int[10]);
그러나 필요합니까? 아마도 사용하는 것이 더 편리하다 std::vector
나 std::array
.
그 구조에 대한 사용을 찾으십니까?
답변
일부 사람들은 std::vector
할당자를 사용 하더라도 고급 기능을 사용할 수 없습니다 . 어떤 사람들은 동적 크기의 배열을 필요로 std::array
합니다. 그리고 어떤 사람들은 배열을 반환하는 것으로 알려진 다른 코드에서 배열을 얻습니다. 그 코드는 vector
또는 다른 것을 반환하기 위해 다시 작성되지 않습니다 .
을 허용 unique_ptr<T[]>
하면 해당 요구 를 처리 할 수 있습니다.
요컨대, 필요할unique_ptr<T[]>
때 사용 합니다. 대안이 단순히 효과가 없을 때. 최후의 수단입니다.
답변
트레이드 오프가 있으며 원하는 것과 일치하는 솔루션을 선택합니다. 내 머리 꼭대기에서 :
초기 크기
vector
그리고unique_ptr<T[]>
크기는 실행 시간에 지정할 수 있습니다array
컴파일시 크기 만 지정할 수 있습니다.
크기 조정
array
및unique_ptr<T[]>
크기 조정 허용하지 않습니다vector
않습니다
저장
vector
및unique_ptr<T[]>
(일반적 힙) 객체 외부에 데이터를 저장할array
객체에 데이터를 직접 저장
사자
array
그리고vector
복사를 허용unique_ptr<T[]>
복사를 허용하지 않습니다
스왑 / 이동
vector
및unique_ptr<T[]>
O (1)이 시간swap
및 이동 동작을array
O (n) 시간swap
및 이동 연산이 있으며 여기서 n은 배열의 요소 수입니다.
포인터 / 참조 / 반복자 무효화
array
객체가 활성화되어있는 동안에도 포인터, 참조 및 반복자가 무효화되지 않도록합니다.swap()
unique_ptr<T[]>
반복자가 없습니다. 포인터와 참조는swap()
객체가 활성화되어있는 동안에 만 무효화됩니다 . 스와핑 한 후에는 포인터가 스왑 한 배열을 가리 키므로 여전히 그런 의미에서 “유효”합니다.vector
재 할당에서 포인터, 참조 및 반복자를 무효화 할 수 있습니다 (재 할당이 특정 작업에서만 발생할 수 있음을 보장합니다).
개념 및 알고리즘과의 호환성
array
그리고vector
둘 다 컨테이너입니다unique_ptr<T[]>
컨테이너가 아닙니다
정책 기반 설계로 리팩토링 할 수있는 기회 인 것 같습니다.
답변
a를 사용하는 한 가지 이유 는 배열 unique_ptr
의 값을 초기화 하는 런타임 비용을 지불하고 싶지 않기 때문 입니다.
std::vector<char> vec(1000000); // allocates AND value-initializes 1000000 chars
std::unique_ptr<char[]> p(new char[1000000]); // allocates storage for 1000000 chars
std::vector
생성자와 std::vector::resize()
초기화 값 것이다 T
– 그러나 new
경우는 그렇게하지 않을 것이다 T
포드입니다.
C ++ 11 및 std :: vector 생성자의 Value-Initialized Objects 참조
참고 vector::reserve
여기에 대안이 아니다는 : 표준 : : 벡터 후에 원시 포인터에 액세스 :: 예비 안전?
그것은 C 프로그래머가 선택할 수 같은 이유 malloc
이상 calloc
.
답변
는 std::vector
동안, 주변에 복사 할 수 있습니다 unique_ptr<int[]>
배열의 고유 한 소유권을 표현 할 수 있습니다. std::array
반면에, 컴파일 타임에 크기를 결정해야하므로 일부 상황에서는 불가능할 수 있습니다.
답변
Scott Meyers는 Effective Modern C ++에서 다음과 같이 말합니다.
의 존재
std::unique_ptr
배열이 있기 때문에, 당신 만 지적 관심을해야한다std::array
,
std::vector
,std::string
거의 항상 원시 배열보다 더 나은 데이터 구조의 선택입니다. 내가std::unique_ptr<T[]>
이해할 수있는 유일한 상황에 대해서는 소유권이 있다고 가정하는 힙 배열에 대한 원시 포인터를 반환하는 C와 같은 API를 사용하는 경우가 될 것입니다.
Charles Salvia의 대답은 관련이 있다고 생각합니다 std::unique_ptr<T[]>
. 컴파일시 크기를 알 수없는 빈 배열을 초기화하는 유일한 방법입니다. Scott Meyers는 이러한 사용 동기에 대해 무엇을 말해야 std::unique_ptr<T[]>
합니까?
답변
반대로 std::vector
하고 std::array
, std::unique_ptr
NULL 포인터를 소유 할 수 있습니다.
이것은 배열 또는 NULL을 기대하는 C API로 작업 할 때 유용합니다.
void legacy_func(const int *array_or_null);
void some_func() {
std::unique_ptr<int[]> ptr;
if (some_condition) {
ptr.reset(new int[10]);
}
legacy_func(ptr.get());
}
답변
내가 사용했던 unique_ptr<char[]>
게임 엔진에 사용되는 사전 할당 된 메모리 풀을 구현 할 수 있습니다. 아이디어는 충돌 요청 결과 및 각 프레임에서 메모리를 할당 / 해제하지 않고도 입자 물리와 같은 다른 것들을 반환하기 위해 동적 할당 대신 사용되는 미리 할당 된 메모리 풀을 제공하는 것입니다. 파괴 논리가 필요하지 않은 (메모리 할당 해제 만) 제한된 수명 시간 (일반적으로 1, 2 또는 3 프레임)으로 객체를 할당하기 위해 메모리 풀이 필요한 이러한 종류의 시나리오에는 매우 편리합니다.