스마트 포인터
Smart pointer컴퓨터 과학에서 스마트 포인터는 자동 메모리 관리 또는 경계 검사와 같은 추가 기능을 제공하면서 포인터를 시뮬레이션하는 추상 데이터 유형입니다.이러한 기능은 효율성을 유지하면서 포인터의 오용으로 인한 버그를 줄이기 위한 것입니다.스마트 포인터는 일반적으로 자신이 가리키는 메모리를 추적하며 네트워크 연결이나 파일 핸들 등의 다른 리소스를 관리하는 데 사용할 수도 있습니다.스마트 포인터는 C++의 자동 쓰레기 [1][2]수집 부족에 대한 비판에 대한 반박으로 1990년대 전반기에 프로그래밍 언어 C++에서 처음 대중화 되었다.
포인터의 오용은 버그의 주요 원인이 될 수 있습니다.스마트 포인터는 메모리 할당을 자동으로 해제하여 대부분의 메모리 누전 상황을 방지합니다.보다 일반적으로 오브젝트 파괴는 자동으로 이루어집니다.예를 들어, 오브젝트의 마지막(또는 유일한) 소유자가 파괴되면 스마트 포인터에 의해 제어되는 오브젝트는 자동으로 파기(완료 후 할당 해제)되고, 실행은 변수의 범위를 벗어나게 됩니다.또한 스마트 포인터는 오브젝트가 더 이상 사용되지 않을 때까지 파괴를 연기함으로써 매달리는 포인터를 제거합니다.
언어가 자동 가비지 수집(Java 또는 C# 등)을 지원하는 경우 스마트 포인터는 메모리 관리의 재확보 및 안전 측면에는 필요하지 않지만 캐시 데이터 구조 상주 관리 및 파일 핸들이나 네트워크 소켓 등의 개체 리소스 관리 등 다른 용도로 유용합니다.
스마트 포인터에는 몇 가지 유형이 있습니다.참조 카운트를 사용하여 작동하는 것도 있고 포인터 하나에 개체의 소유권을 할당하는 것도 있습니다.
역사
C++가 스마트 포인터의 개념, 특히 레퍼런스 카운트의 다양성을 대중화했음에도 불구하고, C++의 디자인에 영감을 준 언어들 중 하나는 레퍼런스 카운트의 레퍼런스가 언어에 내장되어 있었다.C++는 부분적으로 Simula67에서 [3]영감을 받았습니다.Simula67의 조상은 Simula 1세였다.Simula I의 요소가 null이 없는 C++의 포인터와 유사하며, 더미 스테이트먼트를 활동체로 하는 Simula I의 과정은 C++의 구조와 유사하다(그 자체가 C와 유사하다).A. R. Hoare의 당시 1960년대 작품에서의 기록),[4] Simula I는 아래 인용된 단락에서 보듯이 1965년 9월까지 프로세스(즉, 레코드)에 계수된 요소(즉, 간접성을 수용하는 포인터 표현)를 참조했다.
프로세스는 개별적으로 참조할 수 있습니다.물리적으로 프로세스 참조는 프로세스에 대해 로컬인 데이터와 현재 실행 상태를 정의하는 추가 정보를 포함하는 메모리 영역에 대한 포인터입니다.단, 2.2절에서 언급한 이유로 참조는 항상 요소라고 불리는 항목을 통해 간접적이다.공식적으로 프로세스에 대한 참조는 유형 요소의 식 값입니다.
…
요소 값은 요소 변수에 대한 할당 및 참조 및 기타 방법으로 저장 및 검색할 수 있습니다.
언어에는 프로세스의 속성을 외부에서, 즉 다른 프로세스 내에서 액세스할 수 있도록 하는 메커니즘이 포함되어 있습니다.이를 원격 액세스라고 합니다.따라서 프로세스는 참조 가능한 데이터 구조입니다.
활동 주체가 더미 스테이트먼트인 프로세스와 최근 C가 제안한 레코드 개념 간의 유사성을 주목할 필요가 있다.A.R. Hoare와 N.워스
C++는 프로세스/레코드에 새로운 요소를 얻기 위해 프로세스/레코드를 할당할 때 새로운 키워드인 Simula의 메모리 할당 방식을 차용했기 때문에 C++가 결국 요소 내에서 Simula의 참조 카운트된 스마트 포인터 메커니즘을 부활시킨 것은 놀라운 일이 아니다.
특징들
C++에서 스마트 포인터는 오퍼레이터 오버로드에 의해 추가 메모리 관리 기능을 제공하면서 기존의 (원시) 포인터의 동작(예를 들어 참조, 할당)을 모방하는 템플릿 클래스로 구현된다.
스마트 포인터는 포인터의 참조 메모리를 관리하는 방법을 유형으로 표현함으로써 의도적인 프로그래밍을 용이하게 할 수 있습니다.예를 들어, C++ 함수가 포인터를 반환했을 경우, 발신자가 정보를 종료했을 때에, 발신자가 참조의 메모리를 삭제할 필요가 있는지를 알 수 없습니다.
Some Type* 애매하다기능.(); // 결과는 어떻게 해야 합니까?
지금까지 명명 규칙은 오류가 발생하기 쉽고 노동 집약적인 [5]접근 방식인 모호성을 해결하기 위해 사용되어 왔습니다.C++11은 이 경우 함수를 선언하여 올바른 메모리 관리를 보증하는 방법을 도입했습니다.unique_ptr
,
표준::unique_ptr< >Some Type> 명백한 기능();
함수의 반환 타입을 a로 선언합니다.unique_ptr
는, 발신자가 결과의 소유권을 취득하는 것을 명시합니다.또, C++ 런타임에 의해서, 메모리는 자동적으로 재확보됩니다.C++11 이전에는 unique_ptr을 auto_ptr로 대체할 수 있습니다.
새 개체 만들기
의 할당을 용이하게 하려면
표준::shared_ptr< >Some Type>
C++11 소개:
자동 s = 표준::make_shared(공유)< >Some Type>(컨스트럭터, 파라미터, 여기서);
마찬가지로
표준::unique_ptr< >some_type>
C++14에서는 다음을 사용할 수 있습니다.
자동 u = 표준::make_filengths< >Some Type>(컨스트럭터, 파라미터, 여기서);
거의 모든 상황에서 이러한 시설을 사용하는 것이 권장됩니다.new
키워드를 [6]지정합니다.
unique_ptr
C++11의 개요std::unique_ptr
헤더에 정의되어 있습니다.<memory>
를 클릭합니다.[7]
A unique_ptr
raw 포인터의 컨테이너입니다.unique_ptr
소유라고 합니다.aunique_ptr
포함된 포인터의 복사를 명시적으로 금지합니다(통상적인 할당과 마찬가지로).std::move
함수는 포함된 포인터의 소유권을 다른 포인터로 이전하는 데 사용할 수 있습니다.unique_ptr
.aunique_ptr
해당 복사 생성자 및 할당 연산자가 명시적으로 삭제되었기 때문에 복사할 수 없습니다.
표준::unique_ptr< >인트> p1(신규 인트(5)); 표준::unique_ptr< >인트> p2 = p1; // 컴파일 오류입니다. 표준::unique_ptr< >인트> p3 = 표준::움직이다(p1); // 소유권을 이전합니다. 이제 p3이 메모리를 소유하고 p1이 nullptr로 설정됩니다. p3.리셋(); // 메모리를 삭제합니다. p1.리셋(); // 아무것도 하지 않습니다.
std::auto_ptr
C++11에서는 폐지되어 C++17에서는 완전히 삭제됩니다.복사 생성자 및 할당 연산자auto_ptr
저장된 포인터를 실제로 복사하지 않습니다.대신 이전을 남기고 이전을 합니다.auto_ptr
개체가 비어 있습니다.이는 엄격한 소유권을 구현하기 위한 한 가지 방법이며, 따라서 오직 한 가지 방법만이auto_ptr
오브젝트는 언제든지 포인터를 소유할 수 있습니다.즉,auto_ptr
의미 복사가 [8][citation needed]필요한 경우에는 사용하지 마십시오.부터auto_ptr
기존 코드와의 하위 호환성을 손상시키지 않고 이동 전용 포인터로 업그레이드할 수 없습니다.
C++11의 개요std::shared_ptr
그리고.std::weak_ptr
헤더에 정의되어 있습니다.<memory>
.[7] C++11도 도입std::make_shared
(std::make_unique
는, 다이나믹 메모리를 RAII [9]패러다임으로 안전하게 할당하기 위해서, C++14)에 도입되었습니다.
A shared_ptr
raw 포인터의 컨테이너입니다.이 명령어는 포함된 포인터의 참조 카운팅 소유권을 모든 복사본과 함께 유지합니다.shared_ptr
포함된 raw 포인터가 참조하는 오브젝트는 의 모든 복사가 이루어지는 경우에만 파기됩니다.shared_ptr
파괴되었습니다.
표준::shared_ptr< >인트> p0(신규 인트(5)); // 유효하며, 1개의 정수를 할당하고 값 5로 초기화합니다. 표준::shared_ptr< >인트[]> p1(신규 인트[5]); // 유효, 5개의 정수를 할당합니다. 표준::shared_ptr< >인트[]> p2 = p1; // 양쪽이 메모리를 소유하게 되었습니다. p1.리셋(); // p2로 인해 메모리가 아직 존재합니다. p2.리셋(); // 메모리를 다른 사람이 소유하지 않으므로 메모리를 비웁니다.
A weak_ptr
raw 포인터의 컨테이너입니다.의 복사본으로 작성됩니다.shared_ptr
...의 존재 또는 파괴weak_ptr
의 복사본shared_ptr
에 영향을 주지 않다shared_ptr
또는 다른 복사본입니다.의 모든 복사 후shared_ptr
모두 파괴되었다weak_ptr
복사본이 비어 있습니다.
표준::shared_ptr< >인트> p1 = 표준::make_shared(공유)< >인트>(5); 표준::약한_ptr< >인트> wp1 {p1}; // p1이 메모리를 소유합니다. { 표준::shared_ptr< >인트> p2 = wp1.잠그다(); // 이제 p1과 p2가 메모리를 소유하게 되었습니다. // p2는 약한 포인터에서 초기화되어 있기 때문에 p2가 약한 포인터에서 초기화되어 있는지 확인해야 합니다. // 메모리가 아직 존재합니다! 한다면 (p2) { 작업 내용(p2); } } // p2가 파괴되었습니다.메모리는 p1이 소유하고 있습니다. p1.리셋(); // 메모리를 해방합니다. 표준::shared_ptr< >인트> p3 = wp1.잠그다(); // 메모리가 없어졌으므로 빈 shared_ptr이 표시됩니다. 한다면 (p3) { // 코드가 실행되지 않음 액션 That NeedsALive Pointer(p3); }
그 이유는shared_ptr
참조 카운트를 사용하면 순환 참조가 문제가 될 수 있습니다.원형shared_ptr
코드 변경에 의해 체인이 끊어질 수 있습니다.그러면 참조 중 하나가weak_ptr
.
여러 스레드가 안전하게 동시에 액세스 가능shared_ptr
그리고.weak_ptr
동일한 [10]개체를 가리키는 개체입니다.
참조된 개체는 스레드 안전을 보장하기 위해 별도로 보호해야 합니다.
shared_ptr
그리고.weak_ptr
는 Boost [citation needed]라이브러리에서 사용되는 버전을 기반으로 합니다.C++ Technical Report 1(TR1)은 처음에 일반 유틸리티로서 이러한 기능을 표준으로 도입했습니다만, C++11은 Boost 버전에 맞추어 더 많은 기능을 추가했습니다.
「 」를 참조해 주세요.
- 자동 참조 카운트
- 자원 취득은 초기화(RAII)
- auto_ptr
- 불투명 포인터
- 레퍼런스(컴퓨터 사이언스)
- Boost (C++ 라이브러리)
- 뚱뚱한 포인터
- 컴퓨터 프로그래밍의 가비지 컬렉션
레퍼런스
- ^ Kline, Marshall (September 1997). "C++ FAQs Lite's sections on reference-counted smart pointers and copy-on-write reference semantics in the freestore management FAQs". cis.usouthal.edu. Retrieved 2018-04-06.
- ^ Colvin, Gregory (1994). "proposal to standardize counted_ptr in the C++ standard library" (PDF). open-std.org. Retrieved 2018-04-06.
- ^ Stroustrup, Bjarne. "A history of C++: 1979–1991" (PDF). Retrieved 2018-04-06.
- ^ Dahl, Ole-Johan; Nygaard, Kristen (September 1966). "SIMULA—An ALGOL-based simulation language" (PDF). folk.uio.no. Retrieved 2018-04-06.
- ^ "Taligent's Guide to Designing Programs, section Use special names for copy, create, and adopt routines".
- ^ Sutter, Herb (2013-04-20). "Trip Report: ISO C++ Spring 2013 Meeting". isocpp.org. Retrieved 2013-06-14.
- ^ a b ISO 14882:2011 20.7.1
- ^ CERT C++ 시큐어 코딩 규격
- ^ ISO 14882:2014 20.7.1
- ^ "boost::shared_ptr thread safety". (NB. std::shared_ptr에는 정식으로 적용되지 않지만 스레드 제한은 동일한 것으로 생각됩니다).
추가 정보
- Meyers, Scott (2014). Effective Modern C++. Sebastopol, California, USA: O'Reilly Media. ISBN 978-1-49190399-5. OCLC 884480640.
- Alexandrescu, Andrei (2001). "Smart Pointers". Modern C++ Design - Generic Programming and Design Patterns Applied. Addison-Wesley.
- Sutter, Herb (2002-08-01). "The New C++: Smart(er) Pointers".
- 현명한 조언 - 뭐, 왜, 어떤 것?요나트 샤론
- 스마트 포인터의 개요.존 M.Dlugosz
외부 링크
- countptr.hpp.C++ 표준 라이브러리 - Nicolai M. Josuttis의 튜토리얼과 참조
- 스마트 포인터 활성화
- 델파이의 스마트 포인터
- 녹슬어 있는 스마트 포인터
- 현대 C++의 스마트 포인터