[Modern C++] 스마트 포인터 개론
이번에는 스마트 포인터에 대해 간략하게 알아보자.
우선 포인터에 대해 다시 알아보자면 포인터는 양날의 검과 같다.
장점은 메모리에 저장되어 있는 원본 데이터에 접근해서 수정 등이 가능하기 때문에 메모리 절약 및 효율성이
올라가지만, 단점은 메모리 오염이 일어나기 쉽다는 것이다.
A와 B 클래스를 만들어서 동적 할당을 하고 A 클래스에서 B 클래스를 받아서 B 클래스의 데이터를 일부 수정한다고
가정하자. 그러던 도중 B 클래스가 어떤 사유에 의해 동적 할당이 해제되고 그 이후에 A 클래스가 B 클래스의 데이터를
수정하기라도 하면 바로 메모리 오염이 발생한다. 메모리 오염은 매우 치명적이기 때문에 절대로 발생해서는 안 되는
실수이다.
이러한 단점을 보완한 것이 스마트 포인터이다. 좀 더 정확히 설명하자면 스마트 포인터는
포인터를 알맞은 정책에 따라 관리하는 객체를 말한다.
스마트 포인터는 크게 세 가지 개념이 존재한다.
shared_ptr, weak_ptr, unique_ptr
하나하나 알아보도록 하자.
shared_ptr
스마트 포인터에서 가장 대표 격인 친구이다.
shared_ptr은 레퍼런스 카운트를 관리한다. 말 그대로 참조 카운트, 즉 원본 포인터 객체를 몇 명이나 참조하고 있는지
카운트를 하고 있다가 아무도 해당 포인터 객체를 참조하고 있지 않을 때 비로소 delete를 진행한다.
또 한가지 스마트 포인터의 특징이 있는데, 사용자가 명시적으로 delete를 하지 않아도 자동으로 참조를 파악해서
delete를 진행하기 때문에 좀 더 수월한 코딩을 할 수 있다.
이제 shared_ptr의 단점을 얘기해 보자면, shared_ptr을 이용한 객체 A, B가 존재한다고 가정하자.
A는 B를 참조하고 B는 A를 참조하는 상황이다. 즉 서로가 서로를 참조하고 있다. shared_ptr의 특징은 참조하고 있는
객체가 있을 경우 메모리에서 할당이 해제되지 않는다는 점인데 이렇게 서로를 참조하고 있다면 두 객체는 메모리에서
절대 해제되지 않고 계속 남아있게 되는 문제점이 있다. 그렇기 때문에 메모리 할당을 해제하기 전에 포인터 객체를
받아주는 부분을 nullptr로 밀어주어서 할당을 해제해야 한다.
weak_ptr
weak_ptr의 경우 위에서 얘기한 shared_ptr의 단점을 보완하기 위한 ptr이다.
shared_ptr의 경우 내부적으로 참조 카운트를 관리하고 있는데 weak_ptr의 경우 참조 카운트와 더불어
weak 카운트를 관리한다. weak 카운트는 참조하고 있는 객체의 숫자를 나타낸다.
이러한 weak_ptr은 객체의 생명주기에 직접적으로 관여하는 친구는 아니지만 해당 객체가 메모리에서
해제되었는지 아닌지를 체크해주는 기능을 한다.
참고로 expired()로 할당이 해제됐는지 아닌지 체크할 수 있다.
해당 객체가 메모리에 아직 존재한다면 lock() 기능을 이용해서 다시 shared_ptr로 변환을 해주고 원래
사용하던 것처럼 포인터를 이용하면 된다.
정리하자면 weak_ptr를 이용해서 포인터 객체를 받아주고 해당 포인터 객체가 아직 메모리에 존재한다면
shared_ptr로 변환해서 사용하는 방식이다. 즉 shared_ptr를 사용하기 전에 미리 체크한다는 개념으로 생각하면
될 것 같다.
unique_ptr
unique_ptr의 경우 매우 간단하다.
말 그대로 나만 포인터 객체를 가지고 있는 가리키고 있는 형태라고 생각하면 된다.
기본적으로 다른 포인터에게 넘겨주지 못하지만 만약에 넘겨주려고 하면 오른값을 이용해서 넘겨줄 수 있다.
즉 복사는 허용해주지 않고 이동만 허용해주는 포인터라고 생각하면 된다.
'프로그래밍 언어 공부 > C++' 카테고리의 다른 글
[Modern C++] 람다 표현식 (0) | 2022.07.19 |
---|---|
[Modern C++] 전달 참조 (0) | 2022.07.18 |
[Modern C++] 오른값(rvalue) 참조 (0) | 2022.07.16 |
[Modern C++] override, final (0) | 2022.07.15 |
[Modern C++] nullptr (0) | 2022.07.15 |