스마트 포인터 (Smart Pointers)
스마트 포인터는 메모리 관리 문제를 해결하기 위해 C++11에서 도입된 기능입니다. 스마트 포인터는 자동으로 메모리를 관리하여, 메모리 누수와 같은 문제를 줄여줍니다. C++ 표준 라이브러리는 unique_ptr
, shared_ptr
, weak_ptr
라는 세 가지 주요 스마트 포인터를 제공합니다.
unique_ptr
unique_ptr
는 소유권이 단 하나의 객체에만 있는 스마트 포인터입니다. 한 번에 한 객체만 소유권을 가질 수 있으며, 소유권을 다른 객체로 이동할 수 있습니다. unique_ptr
는 가장 가볍고, 소유권 이전을 명확하게 할 수 있는 장점이 있습니다.
1. unique_ptr 기본 사용법
#include <iostream>
#include <memory>
using namespace std;
class MyClass {
public:
MyClass() {
cout << "Constructor called" << endl;
}
~MyClass() {
cout << "Destructor called" << endl;
}
void display() {
cout << "Hello from MyClass" << endl;
}
};
int main() {
unique_ptr<MyClass> ptr1(new MyClass()); // unique_ptr 생성
ptr1->display(); // 포인터를 통해 멤버 함수 호출
// unique_ptr 이동 (ptr1의 소유권을 ptr2로 이동)
unique_ptr<MyClass> ptr2 = move(ptr1);
if (!ptr1) {
cout << "ptr1 is now null" << endl;
}
ptr2->display();
return 0;
}
shared_ptr
shared_ptr
는 여러 개의 스마트 포인터가 하나의 객체를 공유할 수 있게 합니다. 객체의 참조 카운터를 관리하여, 마지막 shared_ptr
이 소멸될 때 객체가 자동으로 삭제됩니다.
1. shared_ptr 기본 사용법
#include <iostream>
#include <memory>
using namespace std;
class MyClass {
public:
MyClass() {
cout << "Constructor called" << endl;
}
~MyClass() {
cout << "Destructor called" << endl;
}
void display() {
cout << "Hello from MyClass" << endl;
}
};
int main() {
shared_ptr<MyClass> ptr1(new MyClass()); // shared_ptr 생성
{
shared_ptr<MyClass> ptr2 = ptr1; // 참조 카운터 증가
ptr2->display();
cout << "ptr2 going out of scope" << endl;
} // ptr2가 범위를 벗어나면서 참조 카운터 감소
cout << "Back in main" << endl;
ptr1->display();
return 0;
}
weak_ptr
weak_ptr
는 shared_ptr
와 함께 사용되어 순환 참조를 방지합니다. weak_ptr
는 객체를 소유하지 않으며, shared_ptr
가 관리하는 객체를 참조합니다. 이를 통해 순환 참조로 인한 메모리 누수를 방지할 수 있습니다.
1. weak_ptr 기본 사용법
#include <iostream>
#include <memory>
using namespace std;
class MyClass {
public:
MyClass() {
cout << "Constructor called" << endl;
}
~MyClass() {
cout << "Destructor called" << endl;
}
void display() {
cout << "Hello from MyClass" << endl;
}
};
int main() {
shared_ptr<MyClass> ptr1(new MyClass()); // shared_ptr 생성
weak_ptr<MyClass> wptr = ptr1; // weak_ptr 생성
// weak_ptr을 shared_ptr로 변환하여 객체에 접근
if (shared_ptr<MyClass> sptr = wptr.lock()) {
sptr->display();
} else {
cout << "The object has been deleted." << endl;
}
return 0;
}
예제 문제
문제 1: unique_ptr을 사용하여 객체 생성 및 소멸 확인
unique_ptr
을 사용하여 객체를 생성하고, 객체의 소멸이 자동으로 이루어지는지 확인하는 프로그램을 작성하세요.
해설:
#include <iostream>
#include <memory>
using namespace std;
class Test {
public:
Test() {
cout << "Constructor called" << endl;
}
~Test() {
cout << "Destructor called" << endl;
}
void show() {
cout << "Hello from Test" << endl;
}
};
int main() {
unique_ptr<Test> ptr1(new Test());
ptr1->show();
unique_ptr<Test> ptr2 = move(ptr1);
if (!ptr1) {
cout << "ptr1 is now null" << endl;
}
ptr2->show();
return 0;
}
이 프로그램은 unique_ptr
을 사용하여 객체를 생성하고, 소멸자가 자동으로 호출되는지 확인합니다.
문제 2: shared_ptr을 사용하여 참조 카운터 확인
shared_ptr
을 사용하여 여러 포인터가 동일한 객체를 참조할 때, 참조 카운터가 어떻게 변하는지 확인하는 프로그램을 작성하세요.
해설:
#include <iostream>
#include <memory>
using namespace std;
class Test {
public:
Test() {
cout << "Constructor called" << endl;
}
~Test() {
cout << "Destructor called" << endl;
}
void show() {
cout << "Hello from Test" << endl;
}
};
int main() {
shared_ptr<Test> ptr1(new Test());
{
shared_ptr<Test> ptr2 = ptr1;
cout << "ptr1 use count: " << ptr1.use_count() << endl;
cout << "ptr2 use count: " << ptr2.use_count() << endl;
}
cout << "ptr1 use count after ptr2 out of scope: " << ptr1.use_count() << endl;
return 0;
}
이 프로그램은 shared_ptr
을 사용하여 참조 카운터가 어떻게 변하는지 확인합니다.
문제 3: weak_ptr을 사용하여 순환 참조 방지
shared_ptr
와 weak_ptr
을 사용하여 순환 참조를 방지하는 프로그램을 작성하세요.
해설:
#include <iostream>
#include <memory>
using namespace std;
class B; // 클래스 B의 전방 선언
class A {
public:
shared_ptr<B> bptr;
~A() {
cout << "A destroyed" << endl;
}
};
class B {
public:
weak_ptr<A> aptr;
~B() {
cout << "B destroyed" << endl;
}
};
int main() {
{
shared_ptr<A> a(new A());
shared_ptr<B> b(new B());
a->bptr = b;
b->aptr = a;
}
// A와 B의 소멸자가 호출되며, 순환 참조가 발생하지 않음을 확인
return 0;
}
이 프로그램은 shared_ptr
과 weak_ptr
을 사용하여 순환 참조를 방지합니다.
다음 단계
25일차의 목표는 C++의 스마트 포인터에 대해 학습하는 것이었습니다. 다음 날부터는 멀티스레딩과 동기화에 대해 다룰 것입니다.
내일은 "멀티스레딩과 동기화"에 대해 다룰 예정입니다. 질문이나 피드백이 있으면 댓글로 남겨 주세요!
'-----ETC----- > C++ 마스터 시리즈' 카테고리의 다른 글
[C++ 마스터] Day 27: 최신 C++ 표준 (C++11, C++14, C++17, C++20) 기능 소개 (0) | 2024.08.01 |
---|---|
[C++ 마스터] Day 24: 프로젝트 - 간단한 콘솔 게임 만들기 (2) (0) | 2024.08.01 |
[C++ 마스터] Day 22: 파일 입출력 (0) | 2024.08.01 |
[C++ 마스터] Day 23: 프로젝트 - 간단한 콘솔 게임 만들기 (1) (0) | 2024.08.01 |
[C++ 마스터] Day 20: STL 벡터와 리스트 (0) | 2024.08.01 |