C++ Algorithm & Study/C++ & Algorithm Strategies

[C++] 14 - 기초 문법 공부 일지(Smart Pointer)

GameChoi 2022. 12. 11. 23:52

1. Smart Pointer (c++ 11)

 - new 및 delete를 사용하여 동적으로 할당받은 메모리는 반드시 해제

 - 메모리 누수 → 프로그램의 안전성을 보장하기 위해 스마트 포인터를 제공하고 있습니다.

 - 포인터처럼 동작하는 클래스 템플릿

   - 사용이 끝난 메모리를 자동 해제

 - Smart Pointer 사용시 소멸자는 객체의 사용이 끝나면 자동 호출

   - 직접 헤체하지 않아도 자동으로 해제

class Knight
{
public:
	Knight(int hp, int maxHp) : hp(hp), maxHp(maxHp) {}

public:
	int hp;
	int maxHp;
};

class SmartPtr
{
public:
	SmartPtr(Knight* k) : kptr(k) {}
	~SmartPtr() { delete kptr; cout << "delete" << endl; }

public:
	Knight* kptr = nullptr;
};

int main()
{
	SmartPtr p = new Knight(100, 100);
    // 종료 시 자동 삭제
}

2. 스마트 포인터의 종류

 - Shared Pointer

   - 하나의 특정 객체를 참조하는 스마트 포인터의 개수를 참조하는 스마트 포인터

     - 참조하고 있는 스마트 포인터의 개수 → reference count

       - 해당 메모리를 참조하는 포인터가 몇개인지 나타내는 값

       - 스마트 포인터가 추가함에따라 1씩 증가 및 사용하지 않으면 1 씩 감소

       - 스마트 포인터가 참조하는 포인터가 0이 됨에 따라 자동으로 메모리 해체

   -  Make Shared

     - 전달받은 인수를 사용하여 지정된 객체를 생성

     - 생성된 객체를 참조하는 shared_ptr을 반환 → 예외발생에 대해 안전하게 생성

 - 자신이 참조하고 있는 객체의 수명에 직접적으로 관여

 - 객체 하나가 소멸되더라도, 동일한 메모리 주소를 참조하는 다른 객체가 있으면 참조하고 있는 객체는 소멸X

class Knight
{
public:
	Knight(int id) : id(id), k(nullptr) {}
	~Knight() {}
	
public:
	int id = 0;
	shared_ptr<Knight> k = nullptr;
};

int main()
{
	shared_ptr<Knight> k1 = make_shared<Knight>(1);
	shared_ptr<Knight> k2 = make_shared<Knight>(2);
	// use_count -> reference count (객체가 현재 가리키고 있는 객체를 참조 중인 소유자의 수를 반환)
	cout << k1.use_count() << endl; // 1
	cout << k2.use_count() << endl; // 1

	k2->k = k1;
	cout << k1.use_count() << endl; // 2
	cout << k2.use_count() << endl; // 1
}

 

- Weak Pointer

   - shared pointer의 객체만 참조, shared_ptr의 reference count를 올리지 않음

   - weak pointer이 shared pointer을 참조할 때 shared pointer의 weak reference count 증가, reference count X

   - 서로가 서로를 가리키는 shared_ptr → reference count가 0이 될 수가 없음

       - 메모리가 해제되지 않는 순환 참조 발생 → weak_ptr 사용(순환 참조를 제거)

class Knight
{
public:
	Knight(int id) : id(id), k(nullptr) {}
	~Knight() {}
	
public:
	int id = 0;
	shared_ptr<Knight> k = nullptr;
};

int main()
{
	shared_ptr<Knight> k1 = make_shared<Knight>(1);
	shared_ptr<Knight> k2 = make_shared<Knight>(2);
	cout << k1.use_count() << endl; // k1 - 1
	cout << k2.use_count() << endl; // k1 - 1
	weak_ptr<Knight> wp1 = k1; // k1 -> weak 1, strong 1
	{
		weak_ptr<Knight> wp2 = k1; // k2 -> weak 2, strong 1
	} // k2 -> weak 1, strong 1 - weak 소멸
	cout << k1.use_count() << endl; // 1
	cout << k2.use_count() << endl; // 1
}

strong / weak

 

- Unique Pointer

   - 하나의 스마트 포인터만이 객체를 가리킴

   - 다른 스마트 포인터를 사용시 move()함수를 사용하여 가리키는 객체를 변경

class Knight
{
public:
	Knight(int id) : id(id), k(nullptr) {}
	~Knight() {}
	
public:
	int id = 0;
	
	shared_ptr<Knight> k = nullptr;
};

int main()
{
	unique_ptr<Knight> k1 (new Knight(1));
	unique_ptr<Knight> k2 = std::move(k1);
}

error