본문 바로가기
Programming/C++

[C++] 스마트포인터와 사용법(unique_ptr, shared_ptr, weak_ptr, auto_pt)

by Winduck 2023. 1. 14.
반응형

※ 스마트 포인터란?


C++ 언어와 다르게 가비지 컬렉터가 없기 때문에 동적으로 할당한 메모리에 대해서는 메모리 누수가 발생하기 쉽습니다.

따라서, 동적으로 할당된 메모리를 관리를 위해 C++14부터 스마트 포인터가 생기게 되었습니다.

스마트 포인터에 동적으로 할당된 메모리 경우 특정 기준에 의해 사용이 완료되었다고 판단이 될 때 메모리를 해제해줍니다.

 

 스마트 포인터 종류


스마트 포인터 설명 비고
unique_ptr 한 객체, 하나의 함수에서 만 사용할 때  사용.  
shared_ptr 특정 포인터의 복사본을 여러 객체나 코드에서 가지고 있을 때(공동 소유권), 이 포인터는 메모리에 대한 참조되는 숫자가 0이 될때 메모리를 해제. 공유될때 마다 레퍼런싱 카운팅을 수행. 
weak_ptr 지정된 메모리에 대한 소유권을 가지지 않는 포인터.
이 때문에 메모리 해제에 대한 영향을 주지 않음.
 
auto_ptr 경우에 따라 자동으로 지정되던 포인터.
(몇가지 큰 에러들이 있어 절대 사용하면 안됨)
C++11, C++14에서 지원X
C++17에서 완전 삭제

 

 사용법


1. unique_ptr 사용법

1) 생성 방법

작성 예제
std::unique_ptr<자료형> 변수명(new 자료형); std::unique_ptr<int> intPtr(new int(20)); // 메모리에 20을 가진 intPtr형 포인터
std::unique_ptr<std::string> strPtr(new std::string("abcd")); //
"abcd"std::string 객체 포인터
auto 변수명 = std::make_unique<자료형>(입력 값) auto intPtr= std::make_unique<int>(20);
// 할당된 int형 포인터 메모리에 20을 입력
auto strPtr= std::make_unique<std::string>("abcd");//
"abcd"std::string 객체 포인터

가독성을 위해 std::make_unique()사용을 권장

 

2) 참조 방법

일반 포인터와 동일하게 아래와 같이 참조

(*test_ptr).run(); 또는 test_ptr->run();으로 표현 됩니다.

 

3) 소유권 이동

std::move()를 통해 소유권을 이동 시킨다.

#include<memory>
#include<iostream>


class Test
{
	public:
    	Test(std::unique_ptr<int> data): mData(std::move(data)){} //소유권 이전
    private:
    	std::unique_ptr<int> mData;
 };
 
 void main()
 {
 	auto originPtr = std::make_unique<int>(20);
    Test t(std::move(originPtr)); // originPtr -> Test생성자 파라미터로 소유권 이전
 }

2. shared_ptr 사용법

1) 생성 방법

auto 변수명 = std::make_shared<자료형>(입력 값); auto int_ptr = std::make_shared(20);
auto strPtr= std::make_shared("abcd");//

2) 캐스팅

const_pointer_cast()

dynamic_pointer_cast()

static_pointer_cast()

reinterpret_pointer_cast() // C++17이후부터

 

3) 참조 방법

일반 포인터와 동일하게 아래와 같이 참조

(*test_ptr).run(); 또는 test_ptr->run();으로 표현 됩니다.

 

4) 앨리어싱(aliasing)

소유 포인터를 다른 shared_ptr과 공유하면서 다른 객체를 가르킬수 있다. 아래코드는 shared_ptr이 객체를 가르키는 동시에 객체 멤버를 동시에 가르킬수 있습니다. 이때 메모리 해제는 t와 aliasing 모두 스코프에서 벗어날때 진행됩니다.

#include<memory>
#include<iostream>

Class Test
{
	private:
    	Test(int data): mData(data){}
        int mData;
};

void main()
{
	auto t  = std::make_shared<Test>(20);
    auto asliaing = std::shared_ptr<int>(t, &t->mData);
}

3. weak_ptr 사용법

1) 생성 방법

weak포인터의 경우 shared_ptr을 가져다가 쓰기 때문에 아래와 같이 사용됩니다.

auto shared변수명 = std::make_shared<자료형>(입력 값);
std::weak_ptr<자료형> weak변수명(shared변수명)
auto int_ptr = std::make_shared(20);
std::weak_ptr<int> weakInt(int_ptr);

2) 사용법

weak_ptr에 저장된 포인터에 접근하려면 shared_ptr로 변환해야한다.

이때 방법은 weak_ptr의 lock()메소드를 사용하는 방법과 weak포인터를 생성할때 shared_ptr을 인수로 전달하는 방법이 있다.

auto int_ptr = std::make_shared(20);
std::weak_ptr<int> weakInt(int_ptr); // shared_ptr을 인수로 넘겨줌

weakInt.lock();//int_ptr의 shared_ptr을 리턴
반응형

'Programming > C++' 카테고리의 다른 글

C 컴파일 과정 (4단계)  (1) 2023.01.19
[C++] 상황에 따른 cast 방법 정리  (0) 2023.01.14
[C++] std::string 클래스 사용법  (0) 2023.01.12
[C++] static 메소드  (0) 2023.01.03
_CRT_SECURE_NO_WARNINGS(C4996)원인 해결 방법  (0) 2022.12.28

댓글