std :: unique_ptr을 선언하는 방법과 그 용도는 무엇입니까?


95

나는 방법을 이해하려고 std::unique_ptr일을하고 내가 발견 문서를. 작성자는 다음 예제에서 시작합니다.

#include <utility>  //declarations of unique_ptr
using std::unique_ptr;
// default construction
unique_ptr<int> up; //creates an empty object
// initialize with an argument
unique_ptr<int> uptr (new int(3));
double *pd= new double;
unique_ptr<double> uptr2 (pd);
// overloaded * and ->
*uptr2 = 23.5;
unique_ptr<std::string> ups (new std::string("hello"));
int len=ups->size();

나에게 헷갈리는 것은이 줄에서

unique_ptr<int> uptr (new int(3));

정수를 인수로 사용합니다 (반올림 괄호 사이).

unique_ptr<double> uptr2 (pd);

포인터를 인수로 사용했습니다. 차이가 있습니까?

나에게도 명확하지 않은 것은 이러한 방식으로 선언 된 포인터가 "정상적인"방식으로 선언 된 포인터와 어떻게 다른지입니다.


13
new int(3)new 에 대한 포인터 int처럼 new에 대한 포인터를 반환합니다 . pddouble
David Schwartz

답변:


89

의 생성자는 unique_ptr<T>유형의 객체에 대한 원시 포인터를 T허용하므로을 허용합니다 T*.

첫 번째 예에서 :

unique_ptr<int> uptr (new int(3));

포인터는 new표현식 의 결과이며 두 번째 예에서는 다음과 같습니다.

unique_ptr<double> uptr2 (pd);

포인터는 pd변수에 저장됩니다 .

개념적으로는 아무것도 변경되지 않지만 ( unique_ptr원시 포인터에서를 생성하고 있음) 두 번째 접근 방식은 예를 들어 다음을 수행 할 수 있기 때문에 잠재적으로 더 위험합니다.

unique_ptr<double> uptr2 (pd);
// ...
unique_ptr<double> uptr3 (pd);

따라서 동일한 객체를 효과적으로 캡슐화하는 두 개의 고유 포인터가 있습니다 (따라서 고유 포인터 의 의미를 위반 함 ).

이것이 가능한 경우 고유 포인터를 만드는 첫 번째 양식이 더 나은 이유입니다. C ++ 14에서는 다음을 수행 할 수 있습니다.

unique_ptr<int> p = make_unique<int>(42);

더 명확하고 안전합니다. 이제 당신의 의심에 대해 :

나에게도 명확하지 않은 것은 이러한 방식으로 선언 된 포인터가 "정상적인"방식으로 선언 된 포인터와 어떻게 다른지입니다.

스마트 포인터는 개체 소유권을 모델링해야하며 해당 개체에 대한 마지막 (스마트, 소유) 포인터가 범위를 벗어날 때 지적 된 개체를 자동으로 제거합니다.

이렇게하면 delete동적으로 할당 된 객체 에 대해 수행하는 것을 기억할 필요가 없습니다 . 스마트 포인터의 소멸자가 자동으로 수행 할 것입니다. 이미 소멸 된 객체에 대한 (매달린) 포인터를 역 참조하지 않을 것인지에 대해 걱정할 필요가 없습니다.

{
    unique_ptr<int> p = make_unique<int>(42);
    // Going out of scope...
}
// I did not leak my integer here! The destructor of unique_ptr called delete

이제는 unique_ptr고유 한 소유권을 모델링하는 스마트 포인터입니다. 즉, 프로그램에서 언제든지 뾰족한 개체에 대한 하나의 (소유) 포인터 만있을 것 unique_ptr입니다. 이것이 복사 할 수없는 이유 입니다.

준수해야하는 암시 적 계약을 위반하지 않는 방식으로 스마트 포인터를 사용하는 한, 메모리가 유출되지 않고 객체에 대한 적절한 소유권 정책이 적용된다는 보장을받을 수 있습니다. 원시 포인터는 이러한 보장을 제공하지 않습니다.


3
안녕하세요, 저는 대해 아무것도 이해할 수 없었다 model object ownership1, integer leak코드 또는를 enforcing ownership policy for object. 이러한 개념을 배우기 위해 주제 / 자원을 제안 해 주시겠습니까?
Flame of udun

1
내가 사용할 수없는 unique_ptr오류를받지 않고, : The text ">" is unexpected. It may be that this token was intended as a template argument list terminator but the name is not known to be a template., 내가 가지고에도 불구 #include <utility>하고 #include <memory>. 어떤 충고?
Anonymous

15

unique_ptr에 할당하는 두 개념 모두에서 작업하는 데 차이가 없습니다.

int* intPtr = new int(3);
unique_ptr<int> uptr (intPtr);

~와 비슷하다

unique_ptr<int> uptr (new int(3));

여기서 unique_ptr 은에서 차지하는 공간을 자동으로 삭제합니다 uptr.


이런 식으로 선언 된 포인터가 "정상적인"방식으로 선언 된 포인터와 어떻게 다른지.

힙 공간에 정수를 생성하는 경우 ( new keyword 또는 malloc 사용 ) 직접 해당 메모리를 지워야합니다 ( 각각 delete 또는 free 사용 ).

아래 코드에서

int* heapInt = new int(5);//initialize int in heap memory
.
.//use heapInt
.
delete heapInt;

여기에서 사용이 완료되면 heapInt 를 삭제 해야합니다 . 삭제하지 않으면 메모리 누수가 발생합니다.

이러한 메모리 누수를 방지하기 위해 unique_ptr 이 사용되며, 여기서 unique_ptr은 범위를 벗어날 때 heapInt가 차지하는 공간을 자동으로 삭제합니다. 따라서 unique_ptr을 삭제 하거나 해제 할 필요가 없습니다 .


10

고유 포인터는 범위를 벗어날 때 관리하는 개체를 파괴하도록 보장됩니다. http://en.cppreference.com/w/cpp/memory/unique_ptr

이 경우 :

unique_ptr<double> uptr2 (pd);

pduptr2범위를 벗어나면 파괴됩니다 . 이는 자동 삭제로 메모리 관리를 용이하게합니다.

의 경우는 unique_ptr<int> uptr (new int(3));원시 포인터가 여기에 어떤 변수에도 할당되지 않는다는 점을 제외하면 다르지 않습니다.


-1

에서 cppreference , 중 하나 std::unique_ptr생성자입니다

명시 적 unique_ptr (포인터 p) noexcept;

따라서 새로 만드는 것은 std::unique_ptr생성자에 대한 포인터를 전달하는 것입니다.

unique_ptr<int> uptr (new int(3));

또는 다음과 같습니다.

int *int_ptr = new int(3);
std::unique_ptr<int> uptr (int_ptr);

다른 점은 사용 후 정리할 필요가 없다는 것입니다. std::unique_ptr(스마트 포인터)를 사용하지 않으시면 이렇게 삭제하셔야합니다.

delete int_ptr;

더 이상 필요하지 않거나 메모리 누수가 발생할 때.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.