C++스마트 포인터 깊이 학습 sharedptr 와 오른쪽 값 참조 방법

1.소개
C++에 쓰레기 회수 메커니즘 이 없 으 면 분 배 된 메모 리 를 스스로 방출 해 야 합 니 다.그렇지 않 으 면 메모리 가 유출 될 수 있 습 니 다.이 문 제 를 해결 하 는 가장 효과 적 인 방법 은 스마트 포인터(smart pointer)를 사용 하 는 것 이다.지능 지침 은 동적 분배(더미)대상 지침 을 저장 하 는 클래스 로 생존 기간 제어 에 사용 되 며 지침 이 있 는 역할 영역 을 벗 어 날 때 동적 분배 대상 을 자동 으로 없 애고 메모리 유출 을 방지 할 수 있다.스마트 포인터 의 핵심 실현 기술 은 인용 계수 입 니 다.사용 할 때마다 내부 인용 계수 에 1 을 더 하고 분석 할 때마다 내부 인용 계수 가 1 을 줄 이 고 0 으로 줄 일 때 가리 키 는 메모 리 를 삭제 합 니 다.
C++11 에서 세 가지 스마트 지침 을 제공 합 니 다.이 스마트 지침 을 사용 할 때 헤더 파일 을 참조 해 야 합 니 다.
  • std::shared_ptr:공유 하 는 스마트 포인터
  • std::unique_ptr:독점 적 인 스마트 포인터
  • std::weak_ptr:약 하 게 인 용 된 스마트 포인터 입 니 다.지침 을 공유 하지 않 고 자원 을 조작 할 수 없습니다.shared 를 감시 하 는 데 사 용 됩 니 다.ptr 의..
  • 공유 지능 포인터(sharedptr)여러 개의 스마트 포인터 가 같은 효과 적 인 메모 리 를 동시에 관리 하고 스마트 포인터 shared 를 공유 하 는 것 을 말한다.ptr 는 템 플 릿 클래스 입 니 다.초기 화 를 하려 면 세 가지 방식 이 있 습 니 다.구조 함수,std:Makeshared 보조 함수 및 reset 방법.공유 스마트 포인터 대상 초기 화 완료 후 관리 할 메모 리 를 가리 키 고 있 습 니 다.현재 몇 개의 스마트 포인터 가 동시에 이 메모 리 를 관리 하고 있 는 지 확인 하려 면 공유 스마트 포인터 가 제공 하 는 구성원 함수 use 를 사용 할 수 있 습 니 다.count
    2.초기 화 방법
    2.1 구조 함수 로 초기 화
    실례
    
    //            int      
    shared_ptr<int> ptr1(new int(520));
    2.2 복사 와 이동 구조 함수 로 초기 화
    복사 구조 함수 호출
    
    shared_ptr<int> ptr2(ptr1);
    이동 구조 함수 호출
    
    std::shared_ptr<int> ptr5 = std::move(ptr2);
    공유 스마트 포인터 대상 을 복사 하 는 방식 으로 초기 화하 면 이 두 대상 은 같은 메모리 더 미 를 동시에 관리 하고 메모리 에 대응 하 는 인용 계수 도 증가 합 니 다.
    모 바 일 방식 으로 초기 스마트 포인터 대상 을 사용 하면 메모리 의 소유권 만 양도 하고 메모리 관리 대상 이 증가 하지 않 기 때문에 메모리 의 인용 수 는 변 하지 않 습 니 다.
    2.2.1 이동 구조
    이동 구조 에 관 해 서 는 일부 독자 들 이 잘 모 를 수도 있다.
    이동 구 조 는 C++11 기준 에서 제공 하 는 새로운 구조 방법 이다.
    현실 에 서 는 우리 가 돈 을 한 계 정 에서 다른 계 정 으로,모 바 일 SIM 카드 를 다른 휴대 전화 로,파일 을 한 위치 에서 다른 위치 로...모 바 일 구 조 는 불필요 한 복 제 를 줄 여 성능 향상 을 가 져 올 수 있다.
    일단 모 브 함 수 를 볼 게 요.
    우선 이런 코드 를 보 겠 습 니 다.
    
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <vector>
    
    using namespace std;
    
    int main()
    {
    	string st = "I love     sir";
    	vector<string> vc;
    	vc.push_back(move(st));
    	cout << vc[0] << endl;
    	if (!st.empty())
    		cout << st << endl;
    
    	return 0;
    }
    출력 결과

    이런 코드 를 다시 보 겠 습 니 다.
    
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <vector>
    
    using namespace std;
    
    int main()
    {
    	string st = "I love xing";
    	vector<string> vc;
    	vc.push_back(st);
    	cout << vc[0] << endl;
    	if (!st.empty())
    		cout << st << endl;
    
    	return 0;
    }
    그 결과

    이 두 단락 코드 의 유일한 차이 점 은 vc.push 호출 입 니 다.back()문자열 을 용기 에 삽입 할 때 첫 번 째 코드 는 move 문 구 를 사 용 했 고 두 번 째 코드 는 move 문 구 를 사용 하지 않 았 습 니 다.출력 결과 차이 도 뚜렷 합 니 다.첫 번 째 코드 에 서 는 원래 문자열 st 가 비어 있 고 두 번 째 코드 에 서 는 원래 문자열 st 의 내용 이 변 하지 않 았 습 니 다.
    이 두 코드 의 출력 결과 간 의 차 이 를 잠시 기억 하 세 요.
    우 리 는 이동 구조 함수 로 돌 아 왔 다.
    가끔 우 리 는 이러한 상황 을 만 날 수 있 습 니 다.우 리 는 대상 a 로 대상 b 를 초기 화하 고 대상 a 를 사용 하지 않 습 니 다.그러나 대상 a 의 공간 은 아직 있 습 니 다.(구조 분석 전에)구조 함 수 를 복사 한 이상 사실은 a 대상 의 내용 을 b 에 복사 하 는 것 입 니 다.그러면 왜 우 리 는 a 의 공간 을 직접 사용 할 수 없 습 니까?이렇게 하면 새로운 공간의 분 배 를 피하 고 구조의 원 가 를 크게 낮 출 수 있다.이것 이 바로 이동 구조 함수 디자인 의 취지 이다.
    통속 적 인 해석 은 복사 구조 함수 에서 지침 에 대해 우 리 는 반드시 심층 복 제 를 사용 해 야 하고 이동 구조 함수 에서 지침 에 대해 우 리 는 얕 은 층 복 제 를 사용 해 야 한 다 는 것 이다.
    따라서 위의 예 에서 모 바 일 구조 함 수 를 호출 하여 스마트 포인터 를 초기 화하 면 인용 수 는 증가 하지 않 고 move 함 수 는 실제 적 으로 돌아 오 는 오른쪽 값 참조 입 니 다.
    2.2.2 오른쪽 값 참조
    위 에서 우 리 는 오른쪽 값 인용 에 대해 말 했 는데,여기 서 오른쪽 값 인용 이 무엇 인지 확장 해 보 자.
    우선 오른쪽 값 이 무엇 인지,왼쪽 값 이 무엇 인지 분명하게 득점 하 다.
    lvalue 는 loactor value 의 줄 임 말 이 고 rvalue 는 read value 의 줄 임 말 입 니 다4.567917.왼쪽 값 은 메모리 에 저장 되 고 명확 한 저장 주소(취 할 수 있 는 주소)가 있 는 데 이 터 를 말한다4.567917.오른쪽 값 은 데이터 값 을 제공 할 수 있 는 데이터(취 할 수 없 는 주소)를 말한다설명 을 통 해 알 수 있 듯 이 왼쪽 값 과 오른쪽 값 을 구분 하 는 편리 한 방법 은 표현 식 에 대한 주소(&)가 왼쪽 값 이 고 그렇지 않 으 면 오른쪽 값 이다.이름 이 있 는 모든 변수 나 대상 은 왼쪽 값 이 고 오른쪽 값 은 익명 입 니 다.
    C++11 에서 오른쪽 값 은 두 가지 로 나 눌 수 있 습 니 다.하 나 는 망 값(xvalue,expiring value)이 고 다른 하 나 는 순 오른쪽 값(prvalue,PureRvalue)입 니 다.
  • 순 오른쪽 값:되 돌아 오 는 임시 변 수 를 참조 하지 않 고 연산 식 에서 발생 하 는 임시 변수,원시 글자 의 양 과 lambda 표현 식 등
  • 망 값:오른쪽 값 과 관련 된 표현 식 을 참조 합 니 다.예 를 들 어 T&&유형 함수 의 반환 값,std:move 의 반환 값 등 입 니 다
  • 오른쪽 값 인용 은 오른쪽 값 을 인용 하 는 형식 입 니 다.오른쪽 값 은 익명 이기 때문에 인용 을 통 해서 만 찾 을 수 있 습 니 다.왼쪽 값 참조 든 오른쪽 값 참조 든 즉시 초기 화 해 야 합 니 다.참조 형식 자체 가 바 인 딩 대상 의 메모리 가 없 기 때문에 이 대상 의 별명 일 뿐 입 니 다.오른쪽 값 참조 성명 을 통 해 이 오른쪽 값 은'다시 태 어 나 기'입 니 다.그 생명 주 기 는 오른쪽 값 참조 유형 변수의 생명 주기 와 마찬가지 로 이 변수 가 살아 있 으 면 이 오른쪽 값 임시 량 은 계속 살아 남 을 것 입 니 다.
    오른쪽 값 은&&를 통 해 참조 합 니 다.
    예 를 들 면:
    4.567917.4.567914.안에 520 은 순 오른쪽 값 이 고 value 는 글자 의 양 520 이라는 오른쪽 값 에 대한 인용 이다4.567917.4.567914.중 a1 은=오른쪽 에 쓰 여 있 지만 왼쪽 값 입 니 다.왼쪽 값 을 사용 하여 오른쪽 값 참조 유형 을 초기 화 하 는 것 은 합 법 적 이지 않 습 니 다4.567917.4.567914.이 코드 의 문법 은 정확 하 다.상수 왼쪽 값 인용 은 만능 인용 유형 으로 왼쪽 값,오른쪽 값,상수 왼쪽 값 과 상수 오른쪽 값 을 받 아들 일 수 있다2.3 std::Make공유 초기 화
    C++를 통 해 제 공 된 std::makeshared()는 메모리 대상 의 생 성 을 완성 하고 스마트 포인터 에 초기 화 할 수 있 습 니 다.함수 원형 은 다음 과 같 습 니 다.
    
    template< class T, class... Args >
    shared_ptr<T> make_shared( Args&&... args );
    실례
    지능 포인터 로 int 형 메모 리 를 관리 하고 내부 인용 수 는 1 입 니 다.
    
    shared_ptr<int> ptr1 = make_shared<int>(520);
    주의 하 다.
    std::make 사용shared()템 플 릿 함 수 는 메모리 주소 생 성 을 완료 하고 최종 적 으로 얻 은 메모리 주 소 를 공유 스마트 포인터 대상 관리 에 전달 할 수 있 습 니 다.신청 한 메모리 가 일반 형식 이 라면 함수 의()를 통 해 주소 초기 화 를 완료 할 수 있 습 니 다.클래스 대상 을 만 들 려 면 함수 의()내부 에 구조 대상 에 필요 한 매개 변 수 를 지정 해 야 합 니 다.즉,클래스 구조 함수 의 매개 변수 입 니 다.
    2.4 reset 방법 으로 초기 화
    공유 스마트 포인터 류 가 제공 하 는 std::sharedptr::reset 방법 함수 원형 은 다음 과 같 습 니 다.
    
    void reset() noexcept;
    
    template< class Y >
    void reset( Y* ptr );
    
    template< class Y, class Deleter >
    void reset( Y* ptr, Deleter d );
    
    template< class Y, class Deleter, class Alloc >
    void reset( Y* ptr, Deleter d, Alloc alloc );
    4.567917.ptr:소유권 을 취득 하려 는 대상 을 가리 키 는 지침d:소유권 을 취득 할 대상 을 가리 키 는 지침내부 저장 에 사용 되 는 분배 기실례
    
    shared_ptr<int> ptr5;
    ptr5.reset(new int(250));
    3.원본 포인터 가 져 오기
    기본 데이터 형식 에 대해 말하자면 스마트 바늘 을 조작 하 는 것 과 스마트 바늘 을 조작 하여 관리 하 는 메모리 효 과 는 같 아서 데이터 의 읽 기와 쓰 기 를 직접 완성 할 수 있다.그러나 공유 스마트 포인터 관리 가 대상 이 라면 원본 메모리 의 주 소 를 꺼 내 서 조작 해 야 합 니 다.공유 스마트 포인터 류 가 제공 하 는 get()방법 으로 원본 주 소 를 얻 을 수 있 습 니 다.그 함수 원형 은 다음 과 같 습 니 다.
    
    T* get() const noexcept;
    실례
    
    #include <iostream>
    #include <string>
    #include <memory>
    using namespace std;
    
    int main()
    {
        int len = 128;
        shared_ptr<char> ptr(new char[len]);
        //          
        char* add = ptr.get();
        memset(add, 0, len);
        strcpy(add, "  :    sir");
        cout << "string: " << add << endl;
        
        shared_ptr<int> p(new int);
        *p = 100;
        cout << *p.get() << "  " << *p << endl;
        
        return 0;
    }
    
    4.삭제 기 지정
    스마트 포인터 가 관리 하 는 메모리 에 대응 하 는 인용 계수 가 0 으로 바 뀌 면 이 메모 리 는 스마트 포인터 에 의 해 분 석 될 것 이다.또한,우 리 는 스마트 포인터 를 초기 화 할 때 삭제 동작 을 스스로 지정 할 수 있 습 니 다.이 삭제 작업 에 대응 하 는 함 수 는 삭제 기 라 고 합 니 다.이 삭제 기 함 수 는 본질 적 으로 리 셋 함수 입 니 다.우 리 는 실현 만 하면 됩 니 다.그 호출 은 스마트 포인터 로 이 루어 집 니 다.
    실례
    
    #include <iostream>
    #include <memory>
    using namespace std;
    
    //         ,  int   
    void deleteIntPtr(int* p)
    {
        delete p;
        cout << "int        ...";
    }
    
    int main()
    {
        shared_ptr<int> ptr(new int(250), deleteIntPtr);
        return 0;
    }
    삭제 기 함수 도 lambda 표현 식 일 수 있 습 니 다!
    5.링크 참조
    https://subingwen.cn/cpp/shared_ptr/
    https://www.cnblogs.com/qingergege/p/7607089.html
    C++스마트 포인터 에 대한 sharedptr 와 오른쪽 값 이 인용 한 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 C++스마트 포인터 내용 은 예전 의 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 도 많은 응원 부 탁 드 리 겠 습 니 다!

    좋은 웹페이지 즐겨찾기