C++학습 의 이동 의미 와 스마트 포인터 상세 설명

이동 의미
1.몇 가지 기본 개념 에 대한 이해
(1)주 소 를 찾 을 수 있 는 것 은 왼쪽 값 입 니 다.주 소 를 찾 을 수 없 는 것 은 오른쪽 값 입 니 다.오른쪽 값 은 레지스터 가 존재 할 수도 있 고 스 택 에 존재 할 수도 있 습 니 다.
(2)오른쪽 값 은 임시 대상,익명 대상,글자 액면가 상수 포함
(3)const 왼쪽 값 인용 은 왼쪽 값 과 오른쪽 값 에 연결 되 어 만능 인용 이 라 고 합 니 다.그 렇 기 때문에 들 어 오 는 매개 변수 가 왼쪽 인지 오른쪽 인지 구분 할 수 없다.

const int &ref = a;//const           
const int &ref1 = 10;//const           
(4)오른쪽 값 참조:오른쪽 값 만 바 인 딩 할 수 있 고 왼쪽 값 으로 바 인 딩 할 수 없습니다.
2.이동 구조 함수
주의:
이동 함수(이동 구조 함수 와 이동 할당 연산 자 함수)는 복사 함수(복사 구조 함수 와 할당 연산 자 함수)의 실행 보다 우선 합 니 다.이동 의미 가 있 는 함수(이동 구조 함수 와 이동 할당 연산 자 함수)는 복사 제어 의미 함수(복사 구조 함수 와 할당 연산 자 함수)의 집행 보다 우선 합 니 다.

String(String &&rhs)
: _pstr(rhs._pstr)
{
cout << "String(String &&)" << endl;
rhs._pstr = nullptr;
}
3.이동 할당 함수

String &operator=(String &&rhs)
{
    cout << "String &operator=(String &&)" << endl;
    if(this != &rhs)//1、   
    {
        delete [] _pstr;//2、      
        _pstr = nullptr;
        _pstr = rhs._pstr;//3、   
        rhs._pstr = nullptr;
    }
    
    return *this;//4、  *this
}
4.std::move 함수
std::move:
원리:왼쪽 값 을 오른쪽 값 으로 바 꾸 고 내부 적 으로 강제 전환 을 했 습 니 다.staticcast(lvaule)。왼쪽 값 을 오른쪽 값 으로 바 꾸 면 왼쪽 값 을 직접 사용 할 수 없 으 며,계속 사용 하려 면 다시 값 을 부여 해 야 합 니 다.std::move()는 내 장 된 유형 에 아무런 역할 을 하지 않 습 니 다.내 장 된 유형 자체 가 왼쪽 값 인지 오른쪽 값 인지 std::move()를 거 친 후에 변 하지 않 습 니 다.
5.면접 문제,String 실현

#include <iostream>
#include <string>

using std::string;
using std::cout;
using std::endl;

class String
{
public:
    //(        )                       
    //      (     )
    String(String &&rhs)
    : _pstr(rhs._pstr)
    {
        cout << "String(String &&)" << endl;
        rhs._pstr = nullptr;
    }

    //         (    )
    String &operator=(String &&rhs)
    {
        cout << "String &operator=(String &&)" << endl;
        if(this!=&rhs){     //     
            delete [] _pstr;//      
            _pstr = nullptr;

            _pstr=rhs._pstr;//        
            rhs._pstr=nullptr;//    
        }
        return *this;
    }

private:
    char* _pstr;
};

자원 관리 와 스마트 포인터
질문
C 언어 는 자원 관 리 를 할 때,예 를 들 어 파일 포인터,분기 가 많 거나 코드 를 쓰 는 사람과 관리자 가 일치 하지 않 아 분기 가 그렇게 완벽 하 게 쓰 이지 않 아 파일 포인터 가 풀 리 지 않 았 기 때문에 C++방식 으로 파일 포인 터 를 관리 할 수 있 습 니 다.

class SafeFile
{
public:
    //          (fp)
    SafeFile(FILE *fp)
    : _fp(fp)
    {
        cout << "SafeFile(FILE *)" << endl;
        if(nullptr==fp)
        {
            cout << "nullptr == _fp " << endl;
        }
    }

    //           
    void write(const string &msg)
    {
        fwrite(msg.c_str(),1,msg.size(),_fp);  //  c      _fp    
    }

    //   (  )      (fp)
    ~SafeFile()
    {
        cout << "~SafeFile()" << endl;
        if(_fp)
        {
            fclose(_fp);
            cout << "fclose(_fp)" << endl;
        }
    }
private:
    FILE *_fp;
};
void test()
{
    string s1 = "hello,world
"; SafeFile sf(fopen("text.txt","a+")); sf.write(s1); }

2.C++의 해결 방법(RAII 기술)
1)개념:자원 관리 RAII 기술,대상 의 생명주기 관리 프로그램 자원(메모리,파일 핸들,잠 금 등 포함)을 이용 한 기술
2)관건:자원 의 방출 순서 가 획득 순서 와 엄 격 히 상반 되 는 것 을 확보 해 야 한다.바로 석조 함수 와 구조 함수 의 작용 이다
3)RAII 흔 한 특징
1.구조 할 때 자원 을 초기 화하 거나 자원 을 위탁 관리 합 니 다.
2.구 조 를 분석 할 때 자원 을 방출 한다.
3.일반적으로 복사 또는 할당 을 허용 하지 않 습 니 다(값 의미-대상 의미)
4.약간의 방문 자원 을 제공 하 는 방법.
4)구분:값 의미:복사 와 할당 이 가능 합 니 다.
5)대상 의 의미:복사 와 할당 을 할 수 없고 보통 두 가지 방법 으로 요구 에 도달 합 니 다.
(1)복사 구조 함수 와 할당 연산 자 함 수 를 개인 적 인 것 으로 설정 하면 ok.
(2),복사 구조 함수 와 할당 연산 자 함수 사용=delete.
6)RAII 기술 코드

template <typename T>
class RAII
{
public:
    //          
    RAII(T *data)
    : _data(data)
    {
        std::cout<< "RAII(T *)" << std::endl;
    }

    //       
    T *operator->()
    {
        return _data;
    }
    T &operator*()
    {
        return *_data;
    }
    T *get()const
    {
        return _data;
    }
    void reset(T *data)
    {
        if(_data)
        {
            delete _data;
            _data = nullptr;
        }
        _data = data;
    }

    //       
    RAII(const RAII&rhs) = delete;
    RAII&operator=(const RAII&rhs)=delete;

    //          
    ~RAII()
    {
        cout << "~RAII()" << endl;
        if(_data)
        {
            delete _data;
            _data = nullptr;
        }
    }


private:
    T *_data;
};
void test3()
{
    //     Point      
    RAII<Point> ppt(new Point(1,2));
    cout<<"ppt = ";
    ppt->print();
    cout<<endl;
}
세 가지,네 가지 지능 지침
레이 이의 대상 ppt 에는 스마트 포인터 의 초기 형태 가 있 습 니 다.
1、auto_ptr.cc
가장 간단 한 스마트 포인터,사용 에 결함 이 있어 버 려 집 니 다...(C++17 이 삭제 되 었 습 니 다)

2、unique_ptr
비 autoptr 가 훨씬 안전 하고 소유권 을 독점 하 는 스마트 포인터 임 을 명 확 히 밝 히 기 때문에 복사 와 할당 을 할 수 없습니다.

    unique_ptr<int> up(new int(10));
    cout<<"*up="<<*up<<endl;              //  10
    cout<<"up.get() = "<<up.get()<<endl;  //         ,   10   

    cout << endl << endl;
    /* unique_ptr<int> up2(up);//error,        ,       */

    unique_ptr<int> up4(std::move(up));  //        up    
    cout<<"*up="<<*up4<<endl;
    cout<<"up.get() = "<<up4.get()<<endl;

    unique_ptr<Point> up5(new Point(3,4));//        up    
    vector<unique_ptr<Point>> numbers;
    numbers.push_back(unique_ptr<Point>(new Point(1,2)));
    numbers.push_back(std::move(up5));
3、shared_ptr

    shared_ptr<int> sp(new int(10));
    cout << "*sp = " << *sp << endl;        //  10
    cout << "sp.get() = " << sp.get() << endl;  //  
    cout << "sp.use_count() = " << sp.use_count() << endl;  //     1

    cout<<endl<<endl;
    //       
    {
        shared_ptr<int> sp2(sp);//     ,     
        cout << "*sp = " << *sp << endl;
        cout << "sp.get() = " << sp.get() << endl;
        cout << "sp.use_count() = " << sp.use_count() << endl;
        cout << "*sp2 = " << *sp2 << endl;
        cout << "sp2.get() = " << sp2.get() << endl;              //     
        cout << "sp2.use_count() = " << sp2.use_count() << endl;  //     1,  2 
    }

    cout << "sp.use_count() = " << sp.use_count() << endl;  //   1 

    cout << endl << endl;
    shared_ptr<Point> sp4(new Point(3.4));//        sp    
    vector<shared_ptr<Point>> numbers;
    numbers.push_back(shared_ptr<Point> (new Point(1,2)));
    numbers.push_back(sp4);
    numbers[0]->print();
    numbers[1]->print();
3.1 반복 참조
이 스마트 포인터 가 사용 할 때 인용 수 를 증가 시 켜 순환 인용 문제 가 발생 합 니 다.두 sharedptr 스마트 포인터 가 서로 가리 키 면 인용 계수 가 증가 하고 대상 의 소각 에 의 해 인용 수 를 0 으로 바 꾸 어 메모리 가 누 출 될 수 없습니다.

class Child;
class Parent
{
public:
  Parent()
 {
    cout << "Parent()" << endl;
 }
  ~Parent()
 {
    cout << "~Parent()" << endl;
 }
  shared_ptr<Child> pParent;
};
class Child
{
public:
  Child()
 {
    cout << "Child()" << endl;
 }
  ~Child()
 {
    cout << "~Child()" << endl;
 }
  shared_ptr<Parent> pChild;
};
void test()
{
  //            
  shared_ptr<Parent> parentPtr(new Parent());
  shared_ptr<Child> childPtr(new Child());
  cout << "parentPtr.use_count() = " << parentPtr.use_count() << endl;
  cout << "childPtr.use_count() = " << childPtr.use_count() << endl;
 
  cout << endl << endl;
  parentPtr->pParent = childPtr;//sp = sp
  childPtr->pChild = parentPtr;
  cout << "parentPtr.use_count() = " << parentPtr.use_count() << endl;
  cout << "childPtr.use_count() = " << childPtr.use_count() << endl;
}
1.순환 인용 을 해결 하 는 방법 은 그 중 하 나 를 weak 로 바 꾸 는 것 이다.ptr,인용 수 를 증가 하지 않 습 니 다.이렇게 하면 대상 의 소각 을 사용 하여 인용 수 를 0 으로 줄 이 는 문 제 를 깨 뜨 릴 수 있 습 니 다.
2.수정:sharedptr pChild;weak 로 변경ptr pChild;순환 인용 문 제 를 해결 할 수 있다.

parentPtr->pParent = childPtr;//sp = sp
childPtr->pChild = parentPtr;//wp = sp,weak_ptr         1
4、weak_ptr
sharedptr 에 비해 약 인용 스마트 포인터,sharedptr 는 강력 한 인용 스마트 포인터 입 니 다.weak_ptr 는 인용 계수 가 증가 하지 않 지만 자원 을 직접 가 져 올 수 없습니다.lock 함 수 를 통 해 wp 에서 sp 로 향상 시 켜 공 유 된 자원 이 폐기 되 었 는 지 판단 해 야 합 니 다.

    weak_ptr<Point> wp
    {
        shared_ptr<Point> sp(new Point(1,2));
        wp = sp;
        cout << "wp.use_count = " << wp.use_count() << endl;
        cout << "sp.use_count = " << sp.use_count() << endl;

        cout<<"wp.expired = "<<wp.expired()<<endl;//      use_count()==0?
        //  0  false,     
        //  0  true,        
        //expired = use_count
        shared_ptr<Point> sp2 = wp.lock();//                   wp   sp
        if(sp2)
        {
            cout << "    " << endl;
        }
        else
        {
            cout << "    " << endl;
        }
     }
4.스마트 포인터 맞 춤 형 삭제 기
1)우 리 는 new 로 공간 을 신청 하고 delete 로 풀 어 주 는 경우 가 많다.라 이브 러 리 에서 실 현 된 각종 스마트 포인터 도 기본적으로 delete 로 공간 을 방출 합 니 다.그러나 만약 에 저희 가 malloc 가 신청 한 공간 이나 fopen 으로 열 린 파일 을 사용 하면 스마트 포인터 가 처리 할 수 없 기 때문에 스마트 포인터 에 삭제 기 를 맞 추고 분석 구 조 를 자 유 롭 게 선택 할 수 있 는 인 터 페 이 스 를 제공 해 야 합 니 다.이렇게 하면...우리 의 스마트 지침 은 서로 다른 형식 으로 열 린 공간 을 처리 하고 파일 지침 을 관리 할 수 있다.
2)스마트 포인터 사용자 정의 방식 은 두 가지 가 있다.
(1)함수 포인터
(2)모방 함수(함수 대상)
함수 포인터 형식:

template<class T>
void Free(T* p)
{
  if (p)
    free(p);
}
template<class T>
void Del(T* p)
{
  if (p)
    delete p;
}
void FClose(FILE* pf)
{
  if (pf)
    fclose(pf);
}
//         
typedef void(*DP)(void*);
template<class T>
class SharedPtr
{
public:
  SharedPtr(T* ptr = NULL ,DP dp=Del)
 :_ptr(ptr)
 , _pCount(NULL)
 , _dp(dp)
 {
    if (_ptr != NULL)
   {
      _pCount = new int(1);
   }
 }
private:
  void Release()
 {
    if (_ptr&&0==--GetRef())
   {
      //delete _ptr;
      _dp(_ptr); 
      delete _pCount;
   }
 }
  int& GetRef()
  {
    return *_pCount;
 }
private:
  T* _ptr;
  int* _pCount;
  DP _dp;
};
모방 함수(함수 대상)
삭제 기 사용

5.스마트 포인터 의 오용
1.같은 누 드 포인터 가 서로 다른 스마트 포인터 에 의 해 위탁 되 어 두 번 분석 되 었 다.
1.1 직접 사용

1.2 간접 사용

2.누 드 포인터 가 스마트 포인터 에 의 해 위탁 관리 되 는 형식 이지 만 비교적 은밀 하 다.

class Point
: public std::enable_shared_from_this<Point>
{
public:
  Point(int ix = 0, int iy = 0)
 : _ix(ix)
 , _iy(iy)
 {
    cout << "Point(int = 0, int = 0)" << endl;
 }
  void print() const
 {
    cout << "(" <<_ix
       << ","  << _iy
       << ")" << endl;
 }
  /* Point *addPoint(Point *pt) */
  shared_ptr<Point> addPoint(Point *pt)
 {
    _ix += pt->_ix;
    _iy += pt->_iy;
    //this        
    /* return shared_ptr<Point>(this); */
    return shared_from_this();
 }
  ~Point()
 {
    cout << "~Point()" << endl;
 }
private:
  int _ix;
  int _iy;
};
void test3()
{
  shared_ptr<Point> sp1(new Point(1, 2));
  cout << "sp1 = ";
  sp1->print();
  cout << endl;
  shared_ptr<Point> sp2(new Point(3, 4));
  cout << "sp2 = ";
  sp2->print();
  cout << endl;
  shared_ptr<Point> sp3(sp1->addPoint(sp2.get()));
  cout << "sp3 = ";
  sp3->print();
}
총결산
C++학습 의 모 바 일 의미 와 스마트 포인터 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 C+모 바 일 의미 와 스마트 포인터 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 도 많은 응원 부탁드립니다!

좋은 웹페이지 즐겨찾기