스마트 포인터 란 무엇이며 언제 사용해야합니까?


1819

스마트 포인터 란 무엇이며 언제 사용해야합니까?


7

2
Visual Studio 2005의 std :: auto_ptr 구현은 끔찍하게 손상되었습니다. 로 <br> http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=98871 로 <br> http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=101842 를 사용하여 대신 부스트하십시오.
Richard

25
주제에 대한 두 가지 훌륭한 기사 :- 스마트 포인터-무엇, 왜, 어느 것? - 이번 주 # 25의 전문가
Lazer

1
여기에 스마트 다른 맛의 포인터 만드는 본격 비교에 Alexandrescu의의 (무료) 장입니다 : informit.com/articles/article.aspx?p=31529 자신의 구현에서이, 그는 (자신이 원하는 어떤 속성을 지정하는 "정책"으로 템플릿 인수를 사용합니다 표준 라이브러리는 별도의 클래스를 사용하는 반면 참조 카운트). 그는 std :: unique_ptr과 같은 것을 가능하게하기 위해 rvalue 참조를 사용할 수 있기 전에 작성했습니다.
metal

위의 질문에 하나 이상의 포인트를 추가하고 싶습니다. 스마트 포인터 std :: shared_ptr에는 첨자 연산자가 없으며 ponter 산술을 지원하지 않습니다. get ()을 사용하여 내장 포인터를 얻을 수 있습니다.
suresh m

답변:


1883

최신 정보

이 답변은 다소 오래되어 부스트 라이브러리에서 제공하는 현명한 포인터 인 당시의 '좋은 것'에 대해 설명합니다. C ++ (11) 때문에, 표준 라이브러리는 충분한 스마트 포인터 유형을 제공하고, 그래서 당신의 사용을 선호한다 std::unique_ptr, std::shared_ptr하고 std::weak_ptr.

또한 있었다 std::auto_ptr. 이 도구는 "특별한"위험한 복사 기능을 가지고 있다는 점을 제외하고는 범위가 지정된 포인터와 매우 유사했습니다.
C ++ 11에서는 더 이상 사용되지 않으며 C ++ 17 에서는 제거되었으므로 사용해서는 안됩니다.

std::auto_ptr<MyObject> p1 (new MyObject());
std::auto_ptr<MyObject> p2 = p1; // Copy and transfer ownership. 
                                 // p1 gets set to empty!
p2->DoSomething(); // Works.
p1->DoSomething(); // Oh oh. Hopefully raises some NULL pointer exception.

오래된 답변

스마트 포인터는 가리키는 객체의 수명을 관리하기 위해 '원시'(또는 '베어') C ++ 포인터를 래핑하는 클래스입니다. 단일 스마트 포인터 유형은 없지만 실제 포인터는 모두 원시 포인터를 추상화하려고합니다.

스마트 포인터는 원시 포인터보다 선호되어야합니다. 포인터를 사용해야한다고 생각한다면 ( 실제로 먼저 고려하십시오 ) 일반적으로 스마트 포인터를 사용하면 원시 포인터의 많은 문제를 해결할 수 있습니다. 주로 객체 삭제 및 메모리 누수를 잊어 버립니다.

원시 포인터를 사용하면 프로그래머는 더 이상 유용하지 않은 객체를 명시 적으로 파괴해야합니다.

// Need to create the object to achieve some goal
MyObject* ptr = new MyObject(); 
ptr->DoSomething(); // Use the object in some way
delete ptr; // Destroy the object. Done with it.
// Wait, what if DoSomething() raises an exception...?

비교에 의한 스마트 포인터는 객체가 파괴 될 때의 정책을 정의합니다. 여전히 객체를 생성해야하지만 더 이상 객체를 파괴 할 염려가 없습니다.

SomeSmartPtr<MyObject> ptr(new MyObject());
ptr->DoSomething(); // Use the object in some way.

// Destruction of the object happens, depending 
// on the policy the smart pointer class uses.

// Destruction would happen even if DoSomething() 
// raises an exception

사용되는 가장 간단한 정책은 boost::scoped_ptr또는에 의해 구현되는 스마트 포인터 래퍼 객체의 범위와 관련됩니다 std::unique_ptr.

void f()
{
    {
       std::unique_ptr<MyObject> ptr(new MyObject());
       ptr->DoSomethingUseful();
    } // ptr goes out of scope -- 
      // the MyObject is automatically destroyed.

    // ptr->Oops(); // Compile error: "ptr" not defined
                    // since it is no longer in scope.
}

참고 std::unique_ptr인스턴스를 복사 할 수 없습니다. 이렇게하면 포인터가 여러 번 잘못 삭제되지 않습니다. 그러나 호출하는 다른 함수에 대한 참조를 전달할 수 있습니다.

std::unique_ptr은 객체의 수명을 특정 코드 블록에 묶거나 다른 객체 내에 멤버 데이터로 포함한 경우 다른 객체의 수명에 유용합니다. 객체는 포함하는 코드 블록이 종료 될 때까지 또는 포함 객체 자체가 파괴 될 때까지 존재합니다.

보다 복잡한 스마트 포인터 정책에는 포인터를 참조하는 참조가 포함됩니다. 포인터를 복사 할 수 있습니다. 객체에 대한 마지막 "참조"가 삭제되면 객체가 삭제됩니다. 이 정책은 boost::shared_ptr및에 의해 구현됩니다 std::shared_ptr.

void f()
{
    typedef std::shared_ptr<MyObject> MyObjectPtr; // nice short alias
    MyObjectPtr p1; // Empty

    {
        MyObjectPtr p2(new MyObject());
        // There is now one "reference" to the created object
        p1 = p2; // Copy the pointer.
        // There are now two references to the object.
    } // p2 is destroyed, leaving one reference to the object.
} // p1 is destroyed, leaving a reference count of zero. 
  // The object is deleted.

참조 카운트 포인터는 객체의 수명이 훨씬 더 복잡하고 특정 코드 섹션이나 다른 객체에 직접 연결되지 않은 경우에 매우 유용합니다.

계산 된 포인터를 참조하는 데는 한 가지 단점이 있습니다. 매달려있는 참조를 만들 수 있습니다.

// Create the smart pointer on the heap
MyObjectPtr* pp = new MyObjectPtr(new MyObject())
// Hmm, we forgot to destroy the smart pointer,
// because of that, the object is never destroyed!

또 다른 가능성은 순환 참조를 작성하는 것입니다.

struct Owner {
   std::shared_ptr<Owner> other;
};

std::shared_ptr<Owner> p1 (new Owner());
std::shared_ptr<Owner> p2 (new Owner());
p1->other = p2; // p1 references p2
p2->other = p1; // p2 references p1

// Oops, the reference count of of p1 and p2 never goes to zero!
// The objects are never destroyed!

이 문제를 해결하기 위해 Boost와 C ++ 11은 모두에 weak_ptr대한 약한 (계산되지 않은) 참조를 정의하도록 a 를 정의했습니다 shared_ptr.


7
당신은 std::auto_ptr<MyObject> p1 (new MyObject());대신에 의미 std::auto_ptr<MyObject> p1 (new Owner());합니까?
Mateen Ulhaq

35
멋진 답변입니다. c ++ 11 용으로 업데이트되면 좋을 것입니다. 이 답변이 새로운 11 표준에 대한 정보를 찾고 있음을 발견했으며 향후 방문자가 업데이트 된 정보를 찾을 수 있다면 좋을 것입니다. auto_ptr이 더 이상 사용되지 않는다는 것을 알고 있습니다. shated_ptr과 weak_ptr은 설명대로 존재한다고 생각하며 scoped_ptr은 표준에서 unique_ptr이라고 생각합니다. 이것이 사실이라면이 답변을 업데이트 할 수 있습니까?
SaulBack

16
매달려있는 참조를 만들 가능성은 참조 카운트 포인터에 대한 단점이라고 말하면 절대적으로 미친 것입니다. 가능한 댕글 링 참조는 모든 C ++ 포인터 의 단점입니다 . 실제로, 스마트 포인터가 완화 하려는 의도 는 바로 그 결점 입니다 .
Michael Dorst

16
스마트 포인터에 대한 포인터를 선언하면 (예제에서와 같이) 스마트 포인터의 모든 이점을 의도적으로 포기합니다. 이것은 단점이나 디자인 결함이 아니며 상상할 수있는 가장 바보 같은 사용법입니다.
Michael Dorst

3
const std::auto_ptrC ++ 03을 사용하는 경우 A 를 사용 하는 것이 안전합니다. C ++ 11에 액세스 할 때까지 pimpl 패턴에 상당히 많이 사용했습니다.
Toby Speight

302

요즘 현대 C ++ (C ++ 11 이상)에 대한 간단한 대답은 다음과 같습니다.

  • 스마트 포인터 란 무엇입니까?
    포인터처럼 값을 사용할 수 있지만 자동 메모리 관리의 추가 기능을 제공하는 유형입니다. 스마트 포인터를 더 이상 사용하지 않으면 가리키는 메모리가 할당 해제됩니다 ( Wikipedia에 대한 자세한 정의 참조 ).
  • 언제 사용해야합니까?
    할당하거나 할당 해제하는 메모리 조각의 소유권을 추적하는 코드; 스마트 포인터는 종종 이러한 작업을 명시 적으로 수행해야 할 필요성을 줄여줍니다.
  • 그러나 어떤 경우에 어떤 스마트 포인터를 사용해야합니까?
    • std::unique_ptr동일한 객체에 대한 여러 참조를 보유하지 않으려는 경우에 사용하십시오 . 예를 들어, 일부 범위를 입력 할 때 할당되고 범위를 종료 할 때 할당이 해제되는 메모리에 대한 포인터에 사용하십시오.
    • std::shared_ptr여러 장소에서 객체를 참조하고 싶을 때 사용 하십시오. 이러한 모든 참조가 사라질 때까지 객체를 할당 해제하지 마십시오.
    • std::weak_ptr여러 곳에서 객체를 참조하고 싶을 때 사용 하십시오-무시하고 할당을 해제하는 참조에 대해서는 참조하십시오 (따라서 역 참조하려고 할 때 객체가 사라 졌다는 것을 알 수 있습니다).
    • boost::스마트 포인터를 사용하지 말고 필요한 std::auto_ptr경우 읽을 수있는 특별한 경우를 제외하고는 사용하지 마십시오 .
  • 이봐 요, 어느 쪽을 사용할 것인지 묻지 않았습니다!
    아,하지만 정말로 인정하고 싶었습니다.
  • 그렇다면 언제 정규 포인터를 사용해야합니까?
    대부분 메모리 소유권을 모르는 코드입니다. 이것은 일반적으로 다른 곳에서 포인터를 가져오고 할당하거나 할당을 해제하지 않고 실행보다 오래 포인터 포인터를 저장하지 않는 함수에 있습니다.

5
스마트 (소유) 포인터는 적절한 메모리 관리에 도움이되지만 원시 (비 소유) 포인터는 여전히 데이터 구조의 다른 조직 목적에 유용합니다. Herb Sutter는 CppCon 2016에서이 문제에 대해 멋진 프레젠테이션을했으며 YouTube 에서 C
wiktor.wandachowicz

1
@ wiktor.wandachowicz는 T*이다 std::unique_ptr<T>무엇 std::weak_ptr<T>이다std::shared_ptr<T>
Caleth

@ 칼 레스 : 아니, 나는 그렇게 말하지 않을 것입니다.
einpoklum

1
@TonyTannous : 관련하여-그것은 주요 편집이었다; 추상적 인 대답이 필요하다고 느끼지 않습니다. 주석으로 링크하여 예제를 별도의 답변으로 만드는 것이 좋습니다.
einpoklum

112

스마트 포인터 는 자동 메모리 할당 해제, 참조 횟수 등과 같은 몇 가지 추가 기능이있는 포인터와 같은 유형입니다.

스마트 포인터-무엇, 왜, 어느 쪽에서 작은 소개를 사용할 수 있습니다 . .

간단한 스마트 포인터 유형 중 하나는 std::auto_ptr(C ++ 표준의 20.4.5 장), 메모리 범위를 벗어난 경우 자동으로 할당을 해제 할 수 있으며, 예외가 발생할 때 단순한 포인터 사용보다 훨씬 유연하지만 유연성이 떨어집니다.

또 다른 편리한 유형은 boost::shared_ptr참조 카운트를 구현하고 객체에 대한 참조가 없을 때 메모리를 자동으로 할당 해제하는 것입니다. 이를 통해 메모리 누수를 방지하고 RAII 를 구현하는 데 쉽게 사용할 수 있습니다.

주제는 "C ++ 템플릿 : 완전한 안내서" 책에서 David Vandevoorde, Nicolai M. Josuttis , 20 장. 스마트 포인터 장에서 자세히 다룹니다. 일부 주제는 다음과 같습니다.


2
std::auto_ptr실수로 소유권을 양도 할 수 있으므로 경고 는 더 이상 사용되지 않으며 사용하지 않는 것이 좋습니다. - C ++ (11)는 부스트, 사용의 필요성을 제거합니다 std::unique_ptr, std::shared_ptr그리고std::weak_ptr
ninMonkey

42

Chris, Sergdev 및 Llyod가 제공 한 정의가 정확합니다. 그러나 나는 인생을 단순하게 유지하기 위해 더 간단한 정의를 선호합니다. 스마트 포인터는 단순히 -> and *연산자에 과부하를주는 클래스입니다 . 개체는 의미 포인터처럼 보이지만 당신은 참조 카운팅, 자동 파괴 등을 포함하여 방법 쿨러의 일을 수행 할 수있는 어떤 수단 shared_ptrauto_ptr대부분의 경우에 충분하지만, 작은 특이 체질의 자신의 세트와 함께 제공됩니다.


30

스마트 포인터는 포인터 자체가 범위를 벗어날 때를 가리키는 점을 제외하고 "char *"와 같은 일반 (유형) 포인터와 같습니다. "->"를 사용하여 일반 포인터처럼 사용할 수 있지만 데이터에 대한 실제 포인터가 필요한 경우에는 사용할 수 없습니다. 이를 위해 "& * ptr"을 사용할 수 있습니다.

다음에 유용합니다.

  • 새 객체로 할당해야하지만 해당 스택의 객체와 동일한 수명을 유지하려는 객체. 객체가 스마트 포인터에 할당 된 경우 프로그램이 해당 기능 / 블록을 종료하면 삭제됩니다.

  • 객체가 삭제되면 소멸자의 특별한 코드없이 소유 한 모든 데이터도 삭제됩니다 (소멸자가 가상인지 확인해야합니다. 거의 항상 좋은 일입니다) .

다음과 같은 경우 스마트 포인터를 사용 하지 않을 수 있습니다 .

  • ... 포인터는 실제로 데이터를 소유해서는 안됩니다. 즉, 데이터를 사용하고있을 때 참조하는 함수에서 살아남기를 원합니다.
  • ... 스마트 포인터 자체가 어느 시점에서 파괴되지는 않습니다. 동적으로 할당되었지만 명시 적으로 삭제되지 않는 객체와 같이 절대로 파괴되지 않는 메모리에 저장하고 싶지 않습니다.
  • ... 두 스마트 포인터가 같은 데이터를 가리킬 수 있습니다. (그러나 그것을 다루는 더 똑똑한 포인터조차 있습니다 ... 참조 카운트 라고 합니다 .)

또한보십시오:


18

대부분의 스마트 포인터는 포인터 대 객체의 처리를 처리합니다. 더 이상 수동으로 객체를 폐기하는 것에 대해 생각할 필요가 없기 때문에 매우 편리합니다.

가장 일반적으로 사용되는 스마트 포인터는 std::tr1::shared_ptr(또는 boost::shared_ptr)이며 덜 일반적 std::auto_ptr입니다. 정기적으로 사용하는 것이 좋습니다 shared_ptr.

shared_ptr는 매우 다재다능하고 객체가 "DLL 경계를 가로 질러 전달"되어야하는 경우 ( libc코드와 DLL간에 서로 다른 코드가 사용되는 경우의 일반적인 악몽 사례)를 포함하여 다양한 처리 시나리오를 처리 합니다.


18

스마트 포인터는 포인터처럼 작동하는 객체이지만 구성, 파괴, 복사, 이동 및 역 참조에 대한 제어 기능을 추가로 제공합니다.

하나는 자신의 스마트 포인터를 구현할 수 있지만 많은 라이브러리는 각각 다른 장점과 단점이있는 스마트 포인터 구현을 제공합니다.

예를 들어, Boost 는 다음과 같은 스마트 포인터 구현을 제공합니다.

  • shared_ptr<T>T객체가 더 이상 필요하지 않은 시점을 판별하기 위해 참조 횟수 를 사용하는 것에 대한 포인터 입니다.
  • scoped_ptr<T>범위를 벗어나면 자동으로 삭제되는 포인터입니다. 할당이 불가능합니다.
  • intrusive_ptr<T>또 다른 참조 카운팅 포인터입니다. 보다 나은 성능 을 제공하지만 자체 참조 계산 메커니즘을 제공 shared_ptr하려면 형식 T이 필요합니다 .
  • weak_ptr<T>shared_ptr순환 참조를 피하기 위해 함께 작동하는 약한 포인터 입니다.
  • shared_array<T>shared_ptr같지만의 배열입니다 T.
  • scoped_array<T>scoped_ptr같지만의 배열입니다 T.

이것들은 각각 하나의 선형 설명이며 필요에 따라 사용할 수 있습니다. 자세한 내용과 예를 들어 Boost 문서를 볼 수 있습니다.

또한 C ++ 표준 라이브러리는 세 가지 스마트 포인터를 제공합니다. std::unique_ptr고유 소유권, std::shared_ptr공유 소유권 및 std::weak_ptr. std::auto_ptrC ++ 03에 존재하지만 더 이상 사용되지 않습니다.


scoped_ptr지역적으로 선언 된 이유 가 아닌 이유를 설명하십시오 const unique_ptr. 범위를 벗어나면 삭제됩니다.
einpoklum

11

비슷한 답변에 대한 링크는 다음과 같습니다. http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

스마트 포인터는 일반 포인터처럼 작동하고 모양과 느낌이 있지만 더 많은 기능을 제공하는 개체입니다. C ++에서 스마트 포인터는 포인터를 캡슐화하고 표준 포인터 연산자를 재정의하는 템플릿 클래스로 구현됩니다. 일반 포인터보다 많은 장점이 있습니다. 이들은 널 포인터 또는 힙 오브젝트에 대한 포인터로 초기화되도록 보장됩니다. 널 포인터를 통한 간접 점검이 점검됩니다. 삭제할 필요가 없습니다. 객체에 대한 마지막 포인터가 사라지면 객체가 자동으로 해제됩니다. 이 스마트 포인터의 중요한 문제 중 하나는 일반 포인터와 달리 상속을 존중하지 않는다는 것입니다. 다형성 코드에는 스마트 포인터가 매력적이지 않습니다. 아래는 스마트 포인터 구현을위한 예입니다.

예:

template <class X>
class smart_pointer
{
          public:
               smart_pointer();                          // makes a null pointer
               smart_pointer(const X& x)            // makes pointer to copy of x

               X& operator *( );
               const X& operator*( ) const;
               X* operator->() const;

               smart_pointer(const smart_pointer <X> &);
               const smart_pointer <X> & operator =(const smart_pointer<X>&);
               ~smart_pointer();
          private:
               //...
};

이 클래스는 X 유형의 객체에 대한 스마트 포인터를 구현합니다. 객체 자체는 힙에 있습니다. 사용 방법은 다음과 같습니다.

smart_pointer <employee> p= employee("Harris",1333);

다른 오버로드 연산자와 마찬가지로 p는 일반 포인터처럼 작동합니다.

cout<<*p;
p->raise_salary(0.5);

9

http://en.wikipedia.org/wiki/Smart_pointer

컴퓨터 과학에서 스마트 포인터는 자동 가비지 수집 또는 범위 검사와 같은 추가 기능을 제공하면서 포인터를 시뮬레이션하는 추상 데이터 형식입니다. 이러한 추가 기능은 포인터의 오용으로 인한 버그를 줄이고 효율성을 유지하기위한 것입니다. 스마트 포인터는 일반적으로 메모리 관리를 위해 개체를 가리키는 개체를 추적합니다. 포인터의 오용은 버그의 주요 원인입니다. 포인터를 사용하여 작성된 프로그램이 수행해야하는 지속적인 할당, 할당 해제 및 참조는 일부 메모리 누수가 발생할 가능성이 높습니다. 스마트 포인터는 리소스 할당을 자동으로 만들어 메모리 누수를 방지하려고합니다. 개체에 대한 포인터 (또는 일련의 포인터에서 마지막)가 파괴되면


6

이 튜토리얼에서 T를 클래스로 사용하자 C ++의 포인터는 3 가지 유형으로 나눌 수 있습니다.

1) 원시 포인터 :

T a;  
T * _ptr = &a; 

메모리 주소를 메모리의 한 위치에 보관합니다. 프로그램을 추적하기가 복잡해 지므로주의해서 사용하십시오.

const 데이터 또는 주소를 가진 포인터 {뒤로 읽기}

T a ; 
const T * ptr1 = &a ; 
T const * ptr1 = &a ;

const 인 데이터 형식 T를 가리키는 포인터. 포인터를 사용하여 데이터 유형을 변경할 수 없음을 의미합니다. 즉 *ptr1 = 19; 작동 안 할 것이다. 그러나 포인터를 움직일 수 있습니다. 즉 ptr1++ , ptr1--; 등이 작동합니다. 뒤로 읽으십시오 : const 인 유형 T에 대한 포인터

  T * const ptr2 ;

데이터 타입 T에 대한 const 포인터. 의미는 포인터를 이동할 수 없지만 포인터가 가리키는 값을 변경할 수 있습니다. 즉 *ptr2 = 19작동하지만 ptr2++ ; ptr2--등은 작동하지 않습니다. 뒤로 읽기 : 타입 T에 대한 const 포인터

const T * const ptr3 ; 

const 데이터 유형 T에 대한 const 포인터 즉, 포인터를 이동할 수 없으며 데이터 유형 포인터를 포인터로 변경할 수 없습니다. 즉. ptr3-- ; ptr3++ ; *ptr3 = 19;작동 안 할 것이다

3) 스마트 포인터 : { #include <memory>}

공유 포인터 :

  T a ; 
     //shared_ptr<T> shptr(new T) ; not recommended but works 
     shared_ptr<T> shptr = make_shared<T>(); // faster + exception safe

     std::cout << shptr.use_count() ; // 1 //  gives the number of " 
things " pointing to it. 
     T * temp = shptr.get(); // gives a pointer to object

     // shared_pointer used like a regular pointer to call member functions
      shptr->memFn();
     (*shptr).memFn(); 

    //
     shptr.reset() ; // frees the object pointed to be the ptr 
     shptr = nullptr ; // frees the object 
     shptr = make_shared<T>() ; // frees the original object and points to new object

포인터로 가리키는 객체를 가리키는 "사물"수를 추적하기 위해 참조 횟수를 사용하여 구현되었습니다. 이 수가 0이되면 객체는 자동으로 삭제됩니다. 즉 객체를 가리키는 모든 share_ptr이 범위를 벗어나면 객체가 삭제됩니다. 이것은 new를 사용하여 할당 한 객체를 삭제 해야하는 두통을 없애줍니다.

약한 포인터 : 공유 포인터를 사용할 때 발생하는 순환 참조 처리에 도움 공유 포인터가 범위를 벗어나면 삭제됩니다. 이를 해결하려면 내부 멤버를 shared_ptr에서 weak_ptr로 변경하십시오. 주 : 약한 포인터가 가리키는 요소에 액세스하려면 lock ()을 사용하여 weak_ptr을 리턴합니다.

T a ; 
shared_ptr<T> shr = make_shared<T>() ; 
weak_ptr<T> wk = shr ; // initialize a weak_ptr from a shared_ptr 
wk.lock()->memFn() ; // use lock to get a shared_ptr 
//   ^^^ Can lead to exception if the shared ptr has gone out of scope
if(!wk.expired()) wk.lock()->memFn() ;
// Check if shared ptr has gone out of scope before access

참조 : std :: weak_ptr은 언제 유용합니까?

Unique Pointer : 독점 소유권이있는 가벼운 스마트 포인터. 포인터가 객체를 공유하지 않고 포인터가 고유 한 객체를 가리킬 때 사용합니다.

unique_ptr<T> uptr(new T);
uptr->memFn(); 

//T * ptr = uptr.release(); // uptr becomes null and object is pointed to by ptr
uptr.reset() ; // deletes the object pointed to by uptr 

고유 한 ptr이 가리키는 오브젝트를 변경하려면 move semantics를 사용하십시오.

unique_ptr<T> uptr1(new T);
unique_ptr<T> uptr2(new T);
uptr2 = std::move(uptr1); 
// object pointed by uptr2 is deleted and 
// object pointed by uptr1 is pointed to by uptr2
// uptr1 becomes null 

참조 : 본질적으로 const 포인터, 즉 const이고 더 나은 구문으로 이동할 수없는 포인터와 같을 수 있습니다.

참조 : C ++에서 포인터 변수와 참조 변수의 차이점은 무엇입니까?

r-value reference : reference to a temporary object   
l-value reference : reference to an object whose address can be obtained
const reference : reference to a data type which is const and cannot be modified 

참조 : https://www.youtube.com/channel/UCEOGtxYTB6vo6MQ-WQ9W_nQ 이 질문을 지적 해 주신 Andre에게 감사드립니다.


3

스마트 포인터는 클래스, 일반 포인터의 래퍼입니다. 일반 포인터와 달리 스마트 포인트의 수명은 기준 카운트 (스마트 포인터 개체가 몇 번 할당되었는지)를 기준으로합니다. 따라서 스마트 포인터가 다른 포인터에 할당 될 때마다 내부 참조 수에 플러스가 더해집니다. 그리고 객체가 범위를 벗어날 때마다 참조 카운트에서 마이너스를 뺍니다.

자동 포인터는 비슷해 보이지만 스마트 포인터와 완전히 다릅니다. 자동 포인터 객체가 변수 범위를 벗어날 때마다 리소스를 할당 해제하는 편리한 클래스입니다. 어느 정도까지는 (동적으로 할당 된 메모리에 대한) 포인터가 스택 변수 (컴파일 시간에 정적으로 할당 됨)와 유사하게 작동합니다.


2

스마트 포인터는 메모리 할당 해제, 리소스 공유 및 전송에 대해 걱정할 필요가없는 것입니다.

Java에서 할당이 작동하는 것과 유사한 방식으로 이러한 포인터를 매우 잘 사용할 수 있습니다. Java Garbage Collector에서는 트릭을 수행하지만 Smart Pointers에서는 소멸자가 트릭을 수행합니다.


1

기존 답변은 훌륭하지만 스마트 포인터가 해결하려는 문제에 대한 (완전한) 답변이 아닌 경우 수행 할 작업은 다루지 않습니다.

스마트 포인터를 사용하는 다른 것들 (다른 답변에서 잘 설명되어 있음) 중에서 추상 클래스를 함수 반환 유형으로 어떻게 사용합니까? 이 질문의 복제본으로 표시되었습니다. 그러나 C ++에서 추상 (또는 실제로) 기본 클래스를 반환 유형으로 지정하려는 유혹을받는 첫 번째 질문은 "실제로 무엇을 의미합니까?"입니다. 부스트 포인터 컨테이너 라이브러리 의 문서에서 C ++의 관용적 객체 지향 프로그래밍 (및 다른 언어와 다른 점)에 대한 좋은 논의가 있습니다 (추가 참조).. 요약하면 C ++에서는 소유권에 대해 생각해야합니다. 어떤 스마트 포인터가 도움이 되나 유일한 솔루션은 아니거나 항상 완전한 솔루션 (다형성 사본을 제공하지 않음)이며 항상 인터페이스에 노출하려는 솔루션이 아닙니다 (함수 리턴은 끔찍한 소리로 들립니다) 인터페이스처럼). 예를 들어 참조를 반환하는 것으로 충분할 수 있습니다. 그러나이 모든 경우 (스마트 포인터, 포인터 컨테이너 또는 단순히 참조 반환) 반환 에서 어떤 형태의 참조로 변경했습니다 . 실제로 복사가 필요한 경우 Adobe Poly 또는 Boost 와 같은 라이브러리를 사용하여 상용구 "이디엄"을 더 추가하거나 C ++의 관용적 OOP를 넘어보다 일반적인 다형성으로 이동해야 할 수 있습니다..

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