스마트포인터 #unique_ptr

UNIQUE_PTR

물론 os 자체에서 메모리를 사용한 후에 해제하지 않더라도 알아서 해제를 해주긴 하지만 서버같은 경우에는 메모리 누수가 나게 되면 작동하는 기간에 따라 메모리가 누적되고 서버가 죽어버리는 과정에 발생한다.

또한 같은 포인터를 공유하고 있는 2 객체가 서로 소멸되면서 해당 포인터의 메모리를 반환하게 된다면, 둘 중 하나는 이미 반환된 메모리를 해제하는 double free 오류가 발생하게 된다. (혹은 이미 반환되었는데 다른 객체가 계속 참조하는 것도 문제가 된다.)

#include <memory> 헤더 파일 포함 필요.

int main(){
	std::unique_ptr<myClass> u_ptr(new myClass());
}

와 같은 방식으로 할당을 하게 된다면, 소멸자에서 자신이 가리키는 포인터의 자원을 해제해주기 때문에 스택이 끝날 때에 안전하게 해제해주게 된다.

그러나 이 기능이 전부가 아닌데, 위와 같이 할당된 unique_ptr은 복사가 불가능하다. std::unique_ptr<myClass> u_ptr2 = u_ptr 과 같은 상황이 발생하지 않는다는 것인데, 내부적으로 대입 연산자를 delete했기 때문이다.

그렇기에 명시적으로 삭제된 복사 / 대입이 불가능하여 한 객체만이 그 포인터를 유일하게 소유하고 있다고 봐도 된다.

만약 그럼에도 소유권을 이전하고 싶다면?

복사 생성자가 아닌, 이동 생성자는 가능하다. 하지만 unique_ptr은 뭐다? 좌측값이다~ 왜냐면 객체니까.

그렇기에 std::unique_ptr<myClass> ptr2 = std::move(ptr1); 과 같이 우측값으로 변환한 뒤에 이동 생성을 하게 되면 문제가 없다.

주의를 해야하는 점이 있다면, 함수의 매개변수로 유니크 포인터의 레퍼런스를 참조하게 된다면. void dontDO(std::unique_ptr<myClass>& _ptr){} 과 같다면 문제 없이 작동할 수도 있다. 이 부분에 대해서는 RAII에 위배되는 것이기 때문에 이렇게 전달해주어선 안된다.

대신 객체의 포인터를 전달해주는 것은 괜찮다. void DOThis(myClass* _ptr){}

앞서 말했듯이, unique_ptr은 객체이기 때문에 L_value다. 만약 데이터 컨테이너에 집어 넣고 싶다면 std::move를 활용할 것!