본문 바로가기
대외활동/시스템프로그래밍

스마트 포인터

by hoshi03 2024. 7. 31.

 

• unique_ptr

 

특정 객체를 가리키는 하나의 스마트 포인터

복사 새성자와 복사 대입 연산자 불가능

 

- 사용법

unique_ptr<클래스> 스마트 포인터명(new 클래스)
unique_ptr<클래스> 스마트 포인터명 = make_unique<클래스>(인수);

 

가능하면 new로 하지 말고 make~로 할것

 

클래스를 스마트 포인터로 호출해보면 따로 delete 하지 않아도 소멸자가 자동으로 호출된다

class T {
public:
	T() { cout << "create t" << endl; }
	~T() { cout << "remove t" << endl; }
};

int main() {
	unique_ptr<T> ptr = make_unique<T>();
	cout << ptr.get() << endl;
}

 

 

- 상속관계

class T {
public:
	T() { cout << "create t" << endl; }
	~T() { cout << "remove t" << endl; }
};

class C : public T {
public:
	C() { cout << "create c" << endl; }
	~C() { cout << "remove c" << endl; }
};

int main() {
	unique_ptr<C> ptr2 = make_unique<C>();
	cout << ptr2.get() << endl;
}

 

위와 같은 상속 관계에서 잘 동작한다

 

-재귀 호출

#include <iostream>
#include <memory>

using namespace std;

void f1(); void f2(); void f3();

class Test {
	int id;
public:
	Test(int n) {
		id = n;
		cout << "생성자 " << id << endl;
	}

	~Test() {
		cout << "소멸자 " << id << endl;
	}
};

void f1() {
	unique_ptr<Test> ptr = make_unique<Test>(1);
	f2();
}

void f2() {
	unique_ptr<Test> ptr = make_unique<Test>(2);
	f3();
}

void f3() {
	unique_ptr<Test> ptr = make_unique<Test>(3);
	throw 10;
}


int main() {
	try
	{
		f1();
	}
	catch (int x)
	{
		cout << "catch block" << endl;
	}

	cout << "main end";
}

 

재귀 호출에서도 생성자 1 2 3 소멸자 3 2 1 순으로 잘 호출된다

 

-move로 메모리 이동

unique_ptr<T> ptr1 = make_unique<T>();
	cout << ptr1.get() << endl;
	unique_ptr<T> ptr2 = make_unique<T>();
	ptr1 = move(ptr2); // move 연산으로 메모리를 옮기는 것은 가능

 

• shared_ptr

 

특정 개체를 여러개의 스마트 포인터가 가리키고

공유시 +, 해제시 -  되는 reference count 라는 변수를 두어서 0이되 면 메모리 해제

shared_ptr<클래스> 스마트    포인터명    = make_shared<클래스>(인수);

 

- use_count 확인

 

처음 생성하고 해제 안하면 1, 다른 데서 참조하면 2로 카운트가 증가했다

int main() {
	shared_ptr<int> ptr = make_shared<int>(10); cout << *ptr << endl;
	cout << ptr.use_count() << endl;
	auto ptr1 = ptr;      // ==> auto ptr1(ptr); 
	cout << ptr1.use_count() << endl;
}

 

- shared_pointer 순환 참조 문제

아래 코드는 서로 참조하는게 계속 유지되서 메모리 해제가 안된다

class Node {
public:
	shared_ptr<Node> next;
	Node() { cout << "Node Create\n"; }
	~Node() { cout << "Node Deleted\n"; }
};


int main() {
	shared_ptr<Node> p1 = make_shared<Node>();
	shared_ptr<Node> p2 = make_shared<Node>();

	p1->next = p2;
	p2->next = p1;
}

 

• weak_ptr

 

shared_ptr가 가리키는 객체를 참조하면서 reference count는 증가시키지 않는다

shared_ptr의 참조 순환 문제를 해결하기 위해서 사용한다

메모리 접근시 멤버 함수 lock() 이용하여 접근한다

 

위 코드의 다음 노드를 가리키는 next를 weak_ptr로 바꾸면 참조 순환 문제가 해결되어 소멸자가 호출된다

class Node {
public:
	weak_ptr<Node> next;
	Node() { cout << "Node Create\n"; }
	~Node() { cout << "Node Deleted\n"; }
};


int main() {
	shared_ptr<Node> p1 = make_shared<Node>();
	shared_ptr<Node> p2 = make_shared<Node>();

	p1->next = p2;
	p2->next = p1;
}

 

-lock을 이용한 weak_ptr 메모리 접근

 

int main() {
	shared_ptr<int> ptr1 = make_shared<int>(1); 
	weak_ptr<int> ptr2 = ptr1;
	cout << "ptr1/ptr2 use_count" << endl;
	cout << ptr1.use_count() << endl;
	cout << ptr2.use_count() << endl;
	*ptr1 = 100;
	cout << "*ptr1 = " << *ptr1 << endl;
	cout << "*ptr2 = " << *(ptr2.lock()) << endl;
}

'대외활동 > 시스템프로그래밍' 카테고리의 다른 글

0805 QT C++ 다양한 ui, 시그널  (0) 2024.08.05
modern c++  (0) 2024.07.31
예외 처리  (0) 2024.07.31
c++ 입출력 시스템  (0) 2024.07.30
람다식  (0) 2024.07.30