2017-12-01 26 views
0

나는 세 가지 클래스를 가지고 : A는, B, 클래스 A에서 C내가 가리키는 대상의 메모리를 관리하지 않는 경우 unique_ptr을 사용해야합니까?

는 C 벡터의 ptrs 단순히 2D 벡터의 요소에서 가리키는 vector<unique_ptr<B>>가 클래스 C의 vector<vector<B>>

있다

필자는이 요소들에 대한 참조만을 원하며이 포인터들로 새로운 메모리를 생성하고 싶지는 않습니다 (그것이 unique_ptrs가하는 일인지 확실하지 않습니다).

이 경우 원시 포인터를 사용하는 것이 더 좋을까요?

편집 : 나는합니다 (ptrs이 범위를 벗어나 갈 때) 벡터가 삭제 될 때 삭제 될 가리키는있어 객체 ​​

+0

"벡터가 삭제 될 때 (ptrs가 범위를 벗어날 때) 가리키고있는 객체를 지우고 싶지 않습니다. *"그런 다음 객체를 벡터에 두지 마십시오. 벡터는 벡터가 삭제 될 때 삭제됩니다. 'vector'는 그 내용을 소유하고'unique_ptr'이 소유 포인터 인 컨테이너이기 때문에,'vector'에서 객체에 대한 unique_ptr을 절대 가져서는 안됩니다. –

+0

@DavidSchwartz하지만 클래스 A에서 벡터에 액세스 할 수 있어야합니다. 더 나은 방법이 있나요? – dramadwarfie

+1

@davidbak : 데이빗 슈 와츠는'vector'가'unique_ptr'을 저장할 수 없다는 의미가 아니라'vector'의 내용에'unique_ptr' * 점을 가지지 말라고 말했습니다. 'vector'는 그 내용을 소유하고 있으며, unique_ptr은 요소의 소유권을 주장하기 위해 heap corruption이 일어나기를 기다리고 있습니다. – ShadowRanger

답변

1

을 원하지 않는 당신은 할 수 없습니다 (물론,하지 않는해야 당신은 모든 것을 부패시키는 것을 좋아한다) new을 통해 (또는 암시 적으로 std::make_unique을 통해) 할당되지 않은 객체를 참조하기 위해 unique_ptr을 사용한다.

원시 포인터를 사용하는 것은 의 2D vector을 완전히 초기화하지 않고 C을 초기화하고 그 다음에 크기를 조정하지 않으면 특히 좋은 생각이 아닙니다. 크기를 조정하면 포인터가 무효화되어 읽지 않으면 정의되지 않은 동작이 발생합니다. vector<vector<std::shared_ptr<B>>>A (std::make_shared를 통해 할당 유형으로 채우기)과 Cvector을 하나 만들

  1. 가 사용

    난 당신의 시나리오에 가장 적합한에 따라 1 2의 옵션을 권 해드립니다 vector<std::shared_ptr<B>> (A에서 삭제하면 C에 영향을 미치지 않습니다 및 관련 사이클이 참조되지 않은 경우)

  2. ( A에서 삭제하면 C에 대한 참조를 제거해야하는 경우) 또는 vector<std::weak_ptr<B>>을3210
  3. A의 논리 지수 (여기서 Avector의 값을 변경하면 C 통해 볼 어떤 변경한다) CC을 변경하는 점을 보유하는 경우

    을 수행합니다. Avector (또는 A 그 자체)에 대한 참조

    b. A vector<std::pair<size_t, size_t>> 여기서 각 pairAvector에 연관된 값을 조회하는 데 사용할 색인을 정의합니다. 옵션 2 A은 (는 vector을 볼 수 있는지 C을 제외하고) 모든 경우에, 많은 변경하지 않는 것을 의미

; vector은 값 기반으로 유지되므로 값을 사용하면 shared_ptr (std::make_shared은 실제로는 3이라는 의미이며, 수동으로 newstd::shared_ptr을 호출하는 경우 4가 됨)를 사용할 때 3-4가 필요하지 않습니다.

0

B 개체가 벡터로 관리되는 경우 A입니다.즉, unique_ptr을 감쌀 필요가 없습니다. 실제로, no-op deleter를 사용하여 unique_ptr을 생성하지 않으면 오류가 발생합니다. 이 경우 객체를 삭제하면 벡터가 객체를 다시 삭제합니다.

C은 개체를 관찰하면되므로 원시 포인터를 사용할 수 있습니다. 비 소유 원시 포인터 (의미가없는 포인터를 delete라고 부름)는 좋습니다.

그러나 이러한 종류의 장기 원시 포인터는 추론하기가 어려울 수 있습니다. 가리키는 개체가 여전히 유효합니까? 어떻게 알았어? 대신 개체에 대한 액세스를 제공하는 A에 API를 추가하고 필요한 경우 포인터를 저장하지 않고 C에만 액세스 할 수 있습니다.