※ 스마트 포인터란?
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 |
댓글