스마트 포인터 (현대 C++)
현대 C++ 프로그래밍에서는 표준 라이브러리를 포함 스마트 포인터프로그램이 있도록 사용 되는 메모리의 여유, 리소스 누수 및 예외가 안전 하 게 보호 됩니다.
스마트 포인터 사용
스마트 포인터에 정의 되어 있는 std 네임 스페이스에는 <memory> 헤더 파일.들은 중요 하는 RAII 또는 자원 획득 된 Initialialization 프로그래밍 방법을.주 목적은 이러한 방법 자원 획득 개체에 대 한 모든 리소스를 만들고 한 줄의 코드로 준비 되어 있도록 개체, 초기화와 동시에 수행 해야 하는 경우실질적으로 RAII의 기본 원리는 모든 힙 할당 리소스 소유권을 제공 하는 것-예를 들어, 동적으로 할당 된 메모리 또는 시스템 개체 핸들-해당 소멸자 코드 삭제 하거나 리소스 및 또한 모든 약속을 포함 하는 스택 할당 개체에 정리 코드를 연결 합니다.
실제 리소스를 가리키는 데 원시 포인터 또는 리소스 핸들을 초기화할 때 대부분의 경우 마우스 포인터에 대 한 스마트 포인터 바로 전달 합니다.현대 C++ 원시 포인터에 작은 코드 블록을 위치 성능이 매우 중요 한 소유권에 대 한 혼동의 가능성이 없는 제한 범위, 루프, 또는 도우미 함수 에서만 사용 됩니다.
다음 예제에서는 원시 포인터 선언 스마트 포인터가 선언에 비교합니다.
void UseRawPointer()
{
// Using a raw pointer -- not recommended.
Song* pSong = new Song(L"Nothing on You", L"Bruno Mars");
// Use pSong...
// Don't forget to delete!
delete pSong;
}
void UseSmartPointer()
{
// Declare a smart pointer on stack and pass it the raw pointer.
unique_ptr<Song> song2(new Song(L"Nothing on You", L"Bruno Mars"));
// Use song2...
wstring s = song2->duration_;
//...
} // song2 is deleted automatically here.
예제에서 알 수 있듯이 스마트 포인터 클래스 템플릿 스택에 선언 하 고 원시는 힙에 할당 된 개체를 가리키는 포인터를 사용 하 여 초기화입니다.스마트 포인터를 초기화 한 후 원시 포인터를 소유 합니다.따라서 스마트 포인터가 원시 포인터를 지정 된 메모리를 삭제 해야 합니다.호출을 삭제 하려면 스마트 포인터 소멸자를 포함 고 스마트 포인터가 스택에 선언 된 때문에 범위, 스마트 포인터를 벗어날 때 스택 더 어딘가에 예외가 발생 하는 경우에 소멸자가 호출 됩니다.
익숙한 포인터 연산자를 사용 하 여 캡슐화 된 포인터가 액세스 -> 및 *, 스마트 포인터 클래스 캡슐화 된 원시 포인터를 반환 하는 오버 로드 되는.
스마트 포인터가 방법은 C++ 개체 만들기 C#와 같은 언어에서는 유사한: 개체를 만들고 다음 주의 정확한 시간에 그것의 시스템을 수 있습니다.차이점 없음 별도 가비지 수집기는 백그라운드에서 실행 되도록 됩니다. 런타임 환경에 빠르고 효율적이 되도록 범위 지정 규칙은 표준 C++를 통해 관리 되는 메모리입니다.
중요 |
---|
항상이 특정 매개 변수 목록 할당 규칙으로 인해 미묘한 리소스 누수가 발생 하지 않습니다 수 있도록 별도 줄의 코드는 매개 변수 목록에 절대로 스마트 포인터를 만듭니다. |
다음 예제는는 unique_ptr 스마트 포인터 형식에는 표준 템플릿 라이브러리에서 큰 개체에 대 한 포인터를 캡슐화 하는 데 수.
class LargeObject
{
public:
void DoSomething(){}
};
void ProcessLargeObject(const LargeObject& lo){}
void SmartPointerDemo()
{
// Create the object and pass it to a smart pointer
std::unique_ptr<LargeObject> pLarge(new LargeObject());
//Call a method on the object
pLarge->DoSomething();
// Pass a reference to a method.
ProcessLargeObject(*pLarge);
} //pLarge is deleted automatically when function block goes out of scope.
이 예제 스마트 포인터를 사용 하 여 다음 필수 단계를 보여 줍니다.
스마트 포인터가 자동 (로컬) 변수로 선언 합니다.(사용 하지 않는 new 또는 malloc 스마트 포인터 식입니다.)
형식 매개 변수를 캡슐화 된 포인터가 가리키는으로 형식을 지정 합니다.
에 대 한 원시 포인터를 전달할는 new-ed 개체의 스마트 포인터의 생성자에서입니다.(일부 유틸리티 기능 또는 스마트 포인터의 생성자가 이러한 작업을 수행 합니다.)
사용 하는 오버 로드 된 -> 및 * 개체에 액세스 하는 연산자입니다.
스마트 포인터가 개체를 삭제할 수 있습니다.
스마트 포인터는 메모리 및 성능 측면에서 모두 가능한 한 효과적으로 되도록 디자인 되었습니다.전용 데이터 멤버에 예를 들어, unique_ptr 캡슐화 된 포인터입니다.따라서 unique_ptr 4 바이트 또는 8 바이트 해당 포인터 같은 크기입니다.오버 로드 된 스마트 포인터를 사용 하 여 캡슐화 된 포인터가 액세스 * 및-> 연산자 원시 포인터를 직접 액세스 보다 성능이 크게 저하 됩니다.
스마트 포인터 자체 멤버 함수는 "점" 표기법을 사용 하 여 액세스할 수 있습니다.예를 들어, 일부 STL 스마트 포인터 reset 멤버 함수 포인터의 소유권을 해제 해야 합니다.이 범위를 벗어나면 스마트 포인터를 이동 하기 전에 다음 예제와 같이 스마트 포인터가 소유 하는 메모리를 확보 하려는 경우에 유용 합니다.
void SmartPointerDemo2()
{
// Create the object and pass it to a smart pointer
std::unique_ptr<LargeObject> pLarge(new LargeObject());
//Call a method on the object
pLarge->DoSomething();
// Free the memory before we exit function block.
pLarge.reset();
// Do some other work...
}
스마트 포인터는 일반적으로 원시 포인터를 직접 액세스할 수 있는 방법을 제공 합니다.STL 스마트 포인터가는 get 이 목적을 위해 멤버 함수 및 CComPtr 가 공용 p 클래스 멤버입니다.내부 포인터에 대 한 직접 액세스를 제공 하 여 코드에서 메모리를 관리 하 고 여전히 스마트 포인터를 지원 하지 않는 코드에 원시 포인터를 전달할 스마트 포인터를 사용할 수 있습니다.
void SmartPointerDemo4()
{
// Create the object and pass it to a smart pointer
std::unique_ptr<LargeObject> pLarge(new LargeObject());
//Call a method on the object
pLarge->DoSomething();
// Pass raw pointer to a legacy API
LegacyLargeObjectFunction(pLarge.get());
}
스마트 포인터의 종류
다음 절 다양 한 종류의 Windows 프로그래밍 환경에서 사용할 수 있는 스마트 포인터를 요약 하 고 사용 시기에 대해 설명 합니다.
C + + 표준 라이브러리의 스마트 포인터
이러한 스마트 포인터 첫 번째 선택으로는 기존의 일반 C++ 개체 (POCO)에 대 한 포인터를 캡슐화 하는 데 사용 합니다.unique_ptr
내부 포인터 하나만 소유자 수 있습니다.POCO에 대 한 특정 요구 하는 알 수 없는 경우 기본 선택 항목으로 사용 된 shared_ptr.새 소유자에 게 이동 있지만 않는 복사 하거나 수 공유 합니다.대체 auto_ptr, 어떤 것 사용 되지 않습니다.비교 boost::scoped_ptr.unique_ptr작고 효율적입니다. 크기 한 포인터 하며 빠른 삽입 하 고 STL 컬렉션을 검색 하는 방법에 대 한 참조가 rvalue를 지원 합니다.헤더 파일: <memory>.자세한 내용은 방법: 만들기 및 unique_ptr 인스턴스를 사용 합니다. 및 unique_ptr Class을 참조하십시오.shared_ptr
스마트 포인터 참조 횟수가 계산 됩니다.컨테이너에서 포인터의 복사본을 반환 하지만 원본 유지 하려는 경우에 여러 명의 소유자, 예를 들어, 하나의 원시 포인터를 할당 하려고 할 때 사용 합니다.원시 포인터까지 모두 삭제 되지 않습니다 shared_ptr 소유자 범위를 벗어난 지나쳤는지 또는 그렇지 않으면 소유권을 부여 합니다.두 포인터 크기 수 있습니다. 개체 및 참조 횟수가 포함 된 공유 제어 블록을 하나 하나입니다.헤더 파일: <memory>.자세한 내용은 방법: 만들고 shared_ptr 인스턴스를 사용 합니다. 및 shared_ptr Class을 참조하십시오.weak_ptr
특별 한 경우 스마트 포인터와 함께에서 사용 하기 위해 shared_ptr.A weak_ptr 하나 이상 소유 하는 개체에 대 한 액세스를 제공 합니다. shared_ptr 인스턴스를 있지만 참조 횟수 관여 하지 않습니다.개체를 관찰할 수 있지만 유지에 필요 하지 않은 경우에 사용 합니다.경우에 따라서는 간의 순환 참조를 중단 하려면 필요한 shared_ptr 인스턴스.헤더 파일: <memory>.자세한 내용은 방법: 만들고 weak_ptr 인스턴스를 사용 합니다. 및 weak_ptr Class을 참조하십시오.
(기본 Windows 프로그래밍) COM 개체에 대 한 스마트 포인터
COM 개체로 작업할 때 적절 한 스마트 포인터 형식이 인터페이스 포인터를 래핑하십시오.다양 한 목적을 위해 여러 개의 스마트 포인터는 ATL (액티브 템플릿 라이브러리)를 정의합니다.수도 있습니다을 _com_ptr_t .tlb 파일에서 래퍼 클래스를 만드는 경우에 컴파일러를 사용 하 여 스마트 포인터 형식입니다.ATL 헤더 파일을 포함 하려는 경우에 가장 적합 합니다.CComPtr 클래스
ATL.를 사용할 수 없는 경우이 옵션을 사용합니다참조 횟수를 사용 하 여 수행의 AddRef 및 Release 방법입니다.자세한 내용은 방법: 만들고 CComPtr 및 CComQIPtr 인스턴스 사용를 참조하십시오.CComQIPtr 클래스
유사한 CComPtr 하지만 또한 단순화 된 구문에 대 한 전화 QueryInterface COM 개체입니다.자세한 내용은 방법: 만들고 CComPtr 및 CComQIPtr 인스턴스 사용를 참조하십시오.CComHeapPtr 클래스
스마트 포인터를 사용 하 여 개체 CoTaskMemFree 메모리를 확보 하십시오.CComGITPtr 클래스
전역 인터페이스 테이블 (GIT)에서 가져온 인터페이스에 대 한 스마트 포인터입니다._com_ptr_t 클래스
유사한 CComQIPtr 기능에서 ATL 헤더에 의존 하지 않지만.
ATL 스마트 포인터 POCO 개체에 대 한
COM 개체에 대 한 스마트 포인터 뿐만 아니라, 스마트 포인터 및 각종 이전 일반 C++ 개체에 대 한 스마트 포인터, 또한 ATL 정의합니다.클래식 Windows 프로그래밍에서 이러한 유용한 대안 STL 컬렉션, 특히 코드 이식성 필요 하지 않은 경우 또는 STL와 ATL의 프로그래밍 모델을 혼합 하려는 경우 형식인CAutoPtr 클래스
고유 소유권 소유권을 이전 하 여 복사본에 적용 하는 스마트 포인터입니다.비교 하 여 사용 되지 않는 std::auto_ptr 클래스입니다.CHeapPtr 클래스
스마트 포인터는 C를 사용 하 여 할당 된 개체에 대 한 malloc 함수.CAutoVectorPtr 클래스
스마트 포인터를 사용 하 여 할당 되는 배열에 대 한 new[].CAutoPtrArray 클래스
배열을 캡슐화 하는 클래스 CAutoPtr 요소입니다.CAutoPtrList 클래스
목록을 조작 하기 위한 메서드를 캡슐화 하는 클래스 CAutoPtr 노드.