C++포인터 가 있 는 구성원 의 클래스 처리 방식 에 대한 상세 한 설명

한 클래스 에서 포인터 가 없 으 면 모든 것 이 편리 합 니 다.기본 으로 합 성 된 석조 함수 가 모든 메모 리 를 자동 으로 처리 하기 때 문 입 니 다.그러나 하나의 클래스 가 포인터 구성원 을 가지 고 있다 면,우리 스스로 분석 함 수 를 써 서 메모 리 를 관리 해 야 한다.에 서 는 하나의 클래스 가 우리 가 직접 석조 함 수 를 써 야 한다 면 이 클래스 도 우리 가 직접 복사 구조 함수 와 복사 할당 함 수 를 써 야 할 것 이 라 고 썼 다.
분석 함수:
클래스 HasPtr 를 정의 합 니 다.이 클래스 에는 int 형식의 지침 이 포함 되 어 있 습 니 다.그리고 석조 함 수 를 정의 합 니 다.이 함 수 는 한 마디 를 인쇄 합 니 다.
HasPtr.h 클래스 의 헤더 파일

#pragma once
#ifndef __HASPTR__
#define __HASPTR__

class HasPtr
{
public:
 HasPtr(int i,int *p);
 //HasPtr& operator=(HasPtr&);
 //HasPtr(const HasPtr&);
 ~HasPtr();
 int get_ptr_value();
 void set_ptr_value(int *p);
 int get_val();
 void set_val(int v);
private:
 int val;
 int *ptr;
};

#endif // !__HASPTR__
HasPtr.cpp 류 의 실현

#include "stdafx.h"

#include <iostream>
#include "HasPtr.h"

using namespace std;

HasPtr::HasPtr(int i, int *p)
{
 val = i;
 ptr = p;
}

int HasPtr::get_ptr_value()
{
 return *ptr;
}

void HasPtr::set_ptr_value(int *p)
{
 ptr = p;
}

int HasPtr::get_val()
{
 return val;
}

void HasPtr::set_val(int v)
{
 val = v;
}

HasPtr::~HasPtr()
{
 cout << "destructor of HasPtr " << endl;
}

ClassWith Pointer 클래스 는 main 입 구 를 포함 하고 HasPtr 는 stack 에 있 습 니 다.

// ClassWithPointer.cpp :              。
//

#include "stdafx.h"
#include <iostream>
#include "HasPtr.h"
using namespace std;

int main()
{
 int temp = 100;
 HasPtr ptr(2,&temp);
 cout << ptr.get_ptr_value() << endl;
 cout << ptr.get_val() << endl;
 system("PAUSE");
 system("PAUSE");
 return 0;
}
이 입구 방법 을 실행 하 였 는데 마지막 에 분석 함수 라 는 말 을 인쇄 하 였 습 니 다.OK.main 방법 에서 stack 에서 HasPtr 를 정 의 했 습 니 다.main 방법 이 종료 되 기 전에 분석 함수 가 자동 으로 호출 되 었 습 니 다.
HasPtr 를 동적 대상 으로 바 꾸 면 쌓 아 올 리 는 것 일 까?
ClassWith Pointer 류 는 main 입 구 를 포함 하고 HasPtr 는 힙 에 있 습 니 다.

// ClassWithPointer.cpp :              。
//

#include "stdafx.h"
#include <iostream>
#include "HasPtr.h"
using namespace std;

int main()
{
 int temp = 100;
 //HasPtr ptr(2,&temp);
 HasPtr *ptr = new HasPtr(2,&temp);
 cout << ptr->get_ptr_value() << endl;
 cout << ptr->get_val() << endl;
 system("PAUSE");
 return 0;
}

실행 해 보 니 석조 함수 가 호출 되 지 않 았 습 니 다.OK,return 0 앞 에 delete ptr 를 추가 합 니 다.석조 함수 가 실행 되 었 다.
그래서 여기에 두 가지 결론 이 있다.
4.567917.대상 이 stack 에 있 을 때 분석 함수 가 자동 으로 호출 됩 니 다4.567917.대상 이 힙 에 있 을 때 delete 문 구 를 호출 해 야 석조 함수 가 실 행 됩 니 다.
현재 분석 함수 에서 delete 문 구 를 호출 하여 포인터 구성원 을 삭제 합 니 다.
헤더 파일 이 변 하지 않 습 니 다.HasPtr.cpp 파일 코드 는 다음 과 같 습 니 다.

 #include "stdafx.h"

#include <iostream>
#include "HasPtr.h"

using namespace std;

HasPtr::HasPtr(int i, int *p)
{
 val = i;
 ptr = p;
}

int HasPtr::get_ptr_value()
{
 return *ptr;
}

void HasPtr::set_ptr_value(int *p)
{
 ptr = p;
}

int HasPtr::get_val()
{
 return val;
}

void HasPtr::set_val(int v)
{
 val = v;
}

HasPtr::~HasPtr()
{
 cout << "destructor of HasPtr " << endl;
 delete ptr;
}

 ClassWithPointer 코드 는 다음 과 같 습 니 다.

// ClassWithPointer.cpp :              。
//

#include "stdafx.h"
#include <iostream>
#include "HasPtr.h"
using namespace std;

int main()
{
 int temp = 100;
 HasPtr ptr(2,&temp);
 cout << ptr.get_ptr_value() << endl;
 cout << ptr.get_val() << endl;
 system("PAUSE");
 return 0;
}

실행 하 십시오.정상적으로 인쇄 가 끝 난 후에 오 류 를 던 집 니 다.

delete 에서 stack 의 포인터 값 을 삭제 할 수 없습니다.
지금 ClassWith Pointer 에 동적 포인터 가 들 어 와 서 테스트 해 보 겠 습 니 다.

// ClassWithPointer.cpp :              。
//

#include "stdafx.h"
#include <iostream>
#include "HasPtr.h"
using namespace std;

int main()
{
int temp = 100;
HasPtr ptr(2,&temp);
cout << ptr.get_ptr_value() << endl;
cout << ptr.get_val() << endl;
system("PAUSE");
return 0;
}

실행 후 석조 함수 가 정상적으로 작 동 합 니 다.그래서 여기에 두 가지 결론 이 있다.
  • delete 문 구 는 stack 의 포인터 값 을 삭제 할 수 없습니다
  • delete 문 구 는 힙 의 포인터 값,즉 new 가 나 온 대상 만 삭제 할 수 있 습 니 다. 
  • 기본 복사 구조 함수 와 기본 할당 작업:
    여기 서 우 리 는 기본 구조 함수 와 기본 할당 작업 을 호출 하여 무엇이 나타 날 지 보 았 습 니 다.편리 하 게 보기 위해 서 저 는 석조 함수 에서 현재 대상 의 주 소 를 인쇄 하고 main 방법 에서 대상 주 소 를 인쇄 했 습 니 다.그러면 어느 대상 이 석조 함 수 를 호출 했 는 지 볼 수 있 습 니 다.
    HasPtr.cpp 코드 는 다음 과 같 습 니 다.
    
    #include "stdafx.h"
    
    #include <iostream>
    #include "HasPtr.h"
    
    using namespace std;
    
    HasPtr::HasPtr(int i, int *p)
    {
     val = i;
     ptr = p;
    }
    
    int HasPtr::get_ptr_value()
    {
     return *ptr;
    }
    
    void HasPtr::set_ptr_value(int *p)
    {
     ptr = p;
    }
    
    int HasPtr::get_val()
    {
     return val;
    }
    
    void HasPtr::set_val(int v)
    {
     val = v;
    }
    
    HasPtr::~HasPtr()
    {
     cout << "destructor of HasPtr " << this << endl;
     delete ptr;
    }
    
    
    ClassWithPointer 코드 는 다음 과 같 습 니 다.
    
    // ClassWithPointer.cpp :              。
    //
    
    #include "stdafx.h"
    #include <iostream>
    #include "HasPtr.h"
    using namespace std;
    
    int main()
    {
     int *temp = new int(100);
     HasPtr ptr(2,temp);
     cout << "ptr-------------->" << &ptr << endl;
     cout << ptr.get_ptr_value() << endl;
     cout << ptr.get_val() << endl;
     
     HasPtr ptr2(ptr);
     cout << "ptr2-------------->" << &ptr2 << endl;
     cout << ptr2.get_ptr_value() << endl;
     cout << ptr2.get_val() << endl;
     
     HasPtr ptr3 = ptr;
     cout << "ptr3-------------->" << &ptr3 << endl;
     cout << ptr3.get_ptr_value() << endl;
     cout << ptr3.get_val() << endl;
    
     system("PAUSE");
     return 0;
    }
    
    운행 결 과 는 다음 과 같 습 니 다.결국 잘못 보 고 했 습 니 다.

    사실 프로그램 이 두 번 째 석조 함수 로 실 행 될 때 잘못 보 고 했 습 니 다.잘못 보 고 된 이 유 는 ptr 가 이미 pending 지침 이 되 었 기 때 문 입 니 다.이 ptr 지침 이 가리 키 는 주 소 는 이미 delete 되 었 기 때 문 입 니 다.
    그러나 우 리 는 최소한 기본 복사 구조 함수 와 할당 작업 을 알 수 있 고 포인터 가 가리 키 는 값 이 아 닌 포인터 값 을 직접 복사 할 수 있 습 니 다.포인터 변수의 값,즉 주소 입 니 다.
    그래서 여기 서 설명 한 문 제 는 대상 의 포인터 구성원 의 메모 리 를 어떻게 관리 하 느 냐 하 는 것 이다.이것 은 핵심 문제 다.
    위의 예 는 기본 적 인 방식 이지 만 관리 에 실 패 했 습 니 다.석조 함수 가 마지막 에 pending 지침 을 삭제 하기 때문에 이상 이 발생 합 니 다. 
    지능 포인터:
    클래스 U 도입Ptr,업무 대상 에 필요 한 포인터 변 수 를 관리 하 는 데 사 용 됩 니 다.int*p 로 가정 합 니 다.헤더 파일 은 다음 과 같 습 니 다:
    
    #pragma once
    #ifndef __UPTR__
    #define __UPTR__
    #include "HasPtr.h"
    #include <iostream>
    
    using namespace std;
    class U_Ptr
    {
     friend class HasPtr;
     int *ip;
     size_t use;
    
     U_Ptr(int *p):ip(p),use(1) {}
     ~U_Ptr() 
     {
      cout << "destruction:"<< *ip << endl;
      delete ip;
     }
    };
    #endif // !__UPTR__
    
    
    현재 우리 의 업무 대상 은 역시 HasPtr 이다.헤더 파일 은 다음 과 같 습 니 다:
    
    #pragma once
    #ifndef __HASPTR__
    #define __HASPTR__
    #include "U_Ptr.h"
    class HasPtr
    {
    public:
     HasPtr(int *p, int i):ptr(new U_Ptr(p)),val(i){}
    
     HasPtr(const HasPtr &orgi) :ptr(orgi.ptr), val(orgi.val) 
     {
      ++ptr->use; 
      cout << "coming into copy construction:" << ptr->use << endl;
     }
    
     HasPtr& operator=(const HasPtr &rhs);
    
     ~HasPtr();
    
     int get_ptr_value() const;
     int get_int() const;
     void set_ptr(int *p);
     void set_int(int i);
    private:
     U_Ptr *ptr;
     int val;
    };
    
    #endif // !__HASPTR__
    
    HasPtr.cpp 는 다음 과 같이 실 현 됩 니 다.
    
    #include "stdafx.h"
    #include "HasPtr.h"
    #include <iostream>
    
    using namespace std;
    
    HasPtr& HasPtr::operator=(const HasPtr &rhs)
    {
     ++rhs.ptr->use;
     if (--ptr->use == 0)
     {
      delete ptr;
     }
     ptr = rhs.ptr;
     val = rhs.val;
     return *this;
    }
    
    HasPtr::~HasPtr()
    {
     cout << "destruction:" << ptr->use << endl;
     if (--ptr->use == 0)
     {
      delete ptr;
     }
    }
    
    int HasPtr::get_ptr_value() const
    {
     return *ptr->ip;
    }
    int HasPtr::get_int() const
    {
     return val;
    }
    void HasPtr::set_ptr(int *p)
    {
     ptr->ip = p;
    }
    void HasPtr::set_int(int i)
    {
     val = i;
    } 
    
    
    테스트 클래스 는 다음 과 같 습 니 다:
    
    // SmartPointer.cpp :              。
    //
    
    #include "stdafx.h"
    #include "HasPtr.h"
    #include <iostream>
    
    using namespace std;
    
    
    int main()
    {
     int *temp = new int(100);
     HasPtr ptr(temp,22);
     cout << "ptr------------>" << endl;
     cout << ptr.get_ptr_value() << endl;
     cout << ptr.get_int() << endl;
     HasPtr ptr2(ptr);
     cout << "ptr2------------>" << endl;
     cout << ptr2.get_ptr_value() << endl;
     cout << ptr2.get_int() << endl;
     system("PAUSE");
     return 0;
    } 
    
    우리 UPtr 는 스마트 포인터 라 고 하 는데 필요 한 포인터 구성원 을 관리 하 는 데 사 용 됩 니 다.Google 의 업무 대상 인 HasPtr 대상 은 스마트 지침 을 포함 하고 있 습 니 다.이 지침 은 HasPtr 대상 이 생 성 될 때 만 들 어 졌 습 니 다.스마트 지침 의 use 변 수 는 업무 대상 인 HasPtr 대상 이 몇 번 복사 되 었 는 지 기록 하 는 데 사 용 됩 니 다.즉,몇 개의 똑 같은 지침 이 ptr 가 가리 키 는 곳 을 가리 키 는 것 입 니까?HasPtr 대상 이 모두 몇 개 같은 지 기록 하려 면 복사 구조 함수 와 할당 작업 에서 use 변 수 를 추가 하고 분석 함수 에서 줄 여야 합 니 다.0 으로 줄 였 을 때 지침 을 삭제 합 니 다.

    좋은 웹페이지 즐겨찾기