logo

C++의 스마트 포인터

전제 조건: C++의 포인터

포인터는 힙 메모리와 같이 프로그램 외부의 리소스에 액세스하는 데 사용됩니다. 따라서 힙 메모리에 액세스하기 위해(힙 메모리 내부에 무언가가 생성된 경우) 포인터가 사용됩니다. 외부 리소스에 액세스할 때 우리는 리소스의 복사본을 사용합니다. 변경사항이 있으면 복사된 버전에서 변경하면 됩니다. 그러나 리소스에 대한 포인터를 사용하면 원래 리소스를 변경할 수 있습니다.



일반 포인터 문제

C++의 일반 포인터와 관련된 일부 문제는 다음과 같습니다.

    메모리 누수: 이는 프로그램에 의해 메모리가 반복적으로 할당되었지만 결코 해제되지 않을 때 발생합니다. 이로 인해 과도한 메모리 소비가 발생하고 결국 시스템 충돌이 발생합니다. 댕글링 포인터(Dangling Pointer): 댕글링 포인터는 포인터 값을 수정하지 않고 객체가 메모리에서 할당 해제될 때 발생하는 포인터입니다. 와일드 포인터: 와일드 포인터는 선언되고 메모리가 할당되는 포인터이지만 포인터는 유효한 개체나 주소를 가리키도록 초기화되지 않습니다. 데이터 불일치: 데이터 불일치는 일부 데이터가 메모리에 저장되어 있지만 일관된 방식으로 업데이트되지 않을 때 발생합니다. 버퍼 오버플로: 포인터가 할당된 메모리 블록 외부의 메모리 주소에 데이터를 쓰는 데 사용되는 경우입니다. 이로 인해 악의적인 공격자가 악용할 수 있는 데이터가 손상됩니다.

예:

C++








// C++ program to demonstrate working of a Pointers> #include> using> namespace> std;> class> Rectangle {> private>:> >int> length;> >int> breadth;> };> void> fun()> {> >// By taking a pointer p and> >// dynamically creating object> >// of class rectangle> >Rectangle* p =>new> Rectangle();> }> int> main()> {> >// Infinite Loop> >while> (1) {> >fun();> >}> }>

>

>

산출

Memory limit exceeded>

설명: 기능 중 재미있는 , 이는 다음을 가리키는 포인터를 생성합니다. 직사각형 물체. 그 물체 직사각형 두 개의 정수를 포함하고, 길이, 그리고 . 기능을 할 때 재미있는 종료되면 p는 지역 변수이므로 소멸됩니다. 하지만 사용하는 것을 잊어버렸기 때문에 소비된 메모리는 할당 해제되지 않습니다. p 삭제; 기능이 끝나면. 즉, 다른 리소스에서 메모리를 자유롭게 사용할 수 없습니다. 하지만 더 이상 변수가 필요하지 않고 메모리가 필요합니다.

기능상, 기본 , 재미있는 무한 루프에서 호출됩니다. 즉, 계속해서 생성된다는 뜻입니다. . 점점 더 많은 메모리를 할당하지만 할당을 취소하지 않았기 때문에 해제되지는 않습니다. 낭비된 메모리는 다시 사용할 수 없습니다. 메모리 누수입니다. 전체 더미 이러한 이유로 메모리가 쓸모 없게 될 수 있습니다.

스마트 포인터

우리가 무의식적으로 포인터 할당을 해제하지 않으면 프로그램 충돌로 이어질 수 있는 메모리 누수가 발생한다는 것을 알고 있습니다. Java, C#의 언어 가비지 수집 메커니즘 다시 사용할 수 있도록 사용되지 않은 메모리를 현명하게 할당 해제합니다. 프로그래머는 메모리 누수에 대해 걱정할 필요가 없습니다. C++에서는 다음과 같은 자체 메커니즘을 제공합니다. 스마트 포인터 . 객체가 파괴되면 메모리도 해제됩니다. 따라서 스마트 포인터가 처리하므로 삭제할 필요가 없습니다.

스마트 포인터 다음과 같은 연산자가 있는 포인터에 대한 래퍼 클래스입니다. * 그리고 -> 과부하. 스마트 포인터 클래스의 객체는 일반 포인터처럼 보입니다. 하지만 달리 일반 포인터, 파괴된 객체 메모리를 할당 해제하고 해제할 수 있습니다.

아이디어는 포인터로 수업을 듣는 것입니다. 파괴자, 그리고 다음과 같은 오버로드된 연산자 * 그리고 -> . 객체가 범위를 벗어나면 소멸자가 자동으로 호출되므로 동적으로 할당된 메모리는 자동으로 삭제됩니다(또는 참조 횟수가 감소될 수 있습니다).

예:

C++




// C++ program to demonstrate the working of Smart Pointer> #include> using> namespace> std;> class> SmartPtr {> >int>* ptr;>// Actual pointer> public>:> >// Constructor: Refer> >// techcodeview.com for use of> >// explicit keyword> >explicit> SmartPtr(>int>* p = NULL) { ptr = p; }> >// Destructor> >~SmartPtr() {>delete> (ptr); }> >// Overloading dereferencing operator> >int>& operator*() {>return> *ptr; }> };> int> main()> {> >SmartPtr ptr(>new> int>());> >*ptr = 20;> >cout << *ptr;> >// We don't need to call delete ptr: when the object> >// ptr goes out of scope, the destructor for it is> >// automatically called and destructor does delete ptr.> >return> 0;> }>

>

>

산출

20>

포인터와 스마트 포인터의 차이점

바늘

스마트 포인터

포인터는 메모리 주소와 해당 메모리 위치에 대한 데이터 유형 정보를 유지하는 변수입니다. 포인터는 메모리의 무언가를 가리키는 변수입니다. 포인터 래핑 스택 할당 객체입니다. 스마트 포인터는 간단히 말해서 포인터 또는 범위가 지정된 포인터를 래핑하는 클래스입니다.
범위를 벗어나도 어떤 형태로든 파괴되지 않습니다. 범위를 벗어나면 스스로 파괴됩니다.
포인터는 다른 기능을 지원하지 않기 때문에 효율적이지 않습니다. 스마트 포인터에는 추가 메모리 관리 기능이 있으므로 더 효율적입니다.
그들은 매우 노동 중심적이고 수동적입니다. 본질적으로 자동/사전 프로그래밍되어 있습니다.

메모: 이것은 다음에서만 작동합니다. 정수 . 그러면 모든 개체에 대해 스마트 포인터를 만들어야 합니까? 아니요 , 해결책이 있습니다 주형 . 아래 코드에서 볼 수 있듯이 어떤 유형이든 가능합니다.

자바에서 배열 정렬

예:

C++




// C++ program to demonstrate the working of Template and> // overcome the issues which we are having with pointers> #include> using> namespace> std;> // A generic smart pointer class> template> <>class> T>>class> SmartPtr {> >T* ptr;>// Actual pointer> public>:> >// Constructor> >explicit> SmartPtr(T* p = NULL) { ptr = p; }> >// Destructor> >~SmartPtr() {>delete> (ptr); }> >// Overloading dereferencing operator> >T& operator*() {>return> *ptr; }> >// Overloading arrow operator so that> >// members of T can be accessed> >// like a pointer (useful if T represents> >// a class or struct or union type)> >T* operator->() {>return> ptr; }> };> int> main()> {> >SmartPtr<>int>>ptr(>new> int>());> >*ptr = 20;> >cout << *ptr;> >return> 0;> }>

>

>

산출

20>

메모: 스마트 포인터는 파일 핸들이나 네트워크 소켓과 같은 리소스 관리에도 유용합니다.

스마트 포인터의 유형

C++ 라이브러리는 다음 유형의 스마트 포인터 구현을 제공합니다.

  • auto_ptr
  • 고유_ptr
  • shared_ptr
  • 약한_ptr

auto_ptr

auto_ptr을 사용하면 새 표현식에서 얻은 개체를 관리하고 auto_ptr 자체가 삭제될 때 해당 개체를 삭제할 수 있습니다. auto_ptr을 통해 개체를 설명하면 단일 할당 개체에 대한 포인터가 저장됩니다.

메모: 이 클래스 템플릿은 C++11부터 더 이상 사용되지 않습니다. Unique_ptr은 기능은 유사하지만 보안이 향상된 새로운 기능입니다.

고유_ptr

고유_ptr 하나의 포인터만 저장합니다. 포인터에서 현재 개체를 제거하여 다른 개체를 할당할 수 있습니다.

C++의 고유 포인터

예:

C++


부락 오즈시비트



// C++ program to demonstrate the working of unique_ptr> // Here we are showing the unique_pointer is pointing to P1.> // But, then we remove P1 and assign P2 so the pointer now> // points to P2.> #include> using> namespace> std;> // Dynamic Memory management library> #include> class> Rectangle {> >int> length;> >int> breadth;> public>:> >Rectangle(>int> l,>int> b)> >{> >length = l;> >breadth = b;> >}> >int> area() {>return> length * breadth; }> };> int> main()> {> // --/ Smart Pointer> >unique_ptr P1(>new> Rectangle(10, 5));> >cout // This'll print 50 // unique_ptr P2(P1); unique_ptr P2; P2 = move(P1); // This'll print 50 cout // cout return 0; }>

>

>

산출

50 50>

shared_ptr

사용하여 shared_ptr 두 개 이상의 포인터가 한 번에 하나의 개체를 가리킬 수 있으며 참조 카운터 사용하여 use_count() 방법.

C++의 공유 포인터

C++




// C++ program to demonstrate the working of shared_ptr> // Here both smart pointer P1 and P2 are pointing to the> // object Addition to which they both maintain a reference> // of the object> #include> using> namespace> std;> // Dynamic Memory management library> #include> class> Rectangle {> >int> length;> >int> breadth;> public>:> >Rectangle(>int> l,>int> b)> >{> >length = l;> >breadth = b;> >}> >int> area() {>return> length * breadth; }> };> int> main()> {> >//---/ Smart Pointer> >shared_ptr P1(>new> Rectangle(10, 5));> >// This'll print 50> >cout shared_ptr P2; P2 = P1; // This'll print 50 cout // This'll now not give an error, cout // This'll also print 50 now // This'll print 2 as Reference Counter is 2 cout << P1.use_count() << endl; return 0; }>

>

>

산출

50 50 50 2>

약한_ptr

Weak_ptr은 객체에 대한 비소유 참조를 보유하는 스마트 포인터입니다. 유지하지 않는다는 점을 제외하면 shared_ptr과 훨씬 더 유사합니다. 참조 카운터 . 이 경우 포인터는 개체에 대한 거점을 갖지 않습니다. 그 이유는 포인터가 객체를 보유하고 다른 객체를 요청한다고 가정하면 포인터가 객체를 형성할 수 있기 때문입니다. 이중 자물쇠.

C++의 약한 포인터

C++




// C++ program to demonstrate the working of weak_ptr> // Here both smart pointer P1 and P2 are pointing to the> // object Addition to which they both does not maintain> // a reference of the object> #include> using> namespace> std;> // Dynamic Memory management library> #include> class> Rectangle {> >int> length;> >int> breadth;> public>:> >Rectangle(>int> l,>int> b)> >{> >length = l;> >breadth = b;> >}> >int> area() {>return> length * breadth; }> };> int> main()> {> >//---/ Smart Pointer> >shared_ptr P1(>new> Rectangle(10, 5));> > >// create weak ptr> >weak_ptr P2 (P1);> > >// This'll print 50> >cout // This'll print 1 as Reference Counter is 1 cout << P1.use_count() << endl; return 0; }>

>

>

산출

50 1>

C++ 라이브러리는 auto_ptr, Unique_ptr, shared_ptr 및 Weak_ptr 형식의 스마트 포인터 구현을 제공합니다.