메모리를 직접 관리하는 c++에서 dagling pointer가 발생하지 않도록 스마트 포인터를 제공한다.
- unique_ptr - 객체에 대한 단일 소유권을 관리 (두개의 포인터가 하나의 공간을 소유할 수 없음, move를 통해 소유권 이전은 가능)
- shared_ptr - 레퍼런스 카운트를 관리 (현재 객체를 참조하는 포인터의 개수를 카운팅하는 것)
- weak_ptr - 객체의 소유권을 공유하지 않음 (shared_ptr은 서로를 가리켜 메모리 누수를 유발할 수 있기에 둘중에 하나를 weak_ptr로 대체하면 순환 고리가 끊어지게 됨)
사용법
#include <iostream>
#include <memory> //스마트 포인터 사용
using namespace std;
int main() {
// unique_ptr 생성
unique_ptr<int> ptr1 = make_unique<int>(20);
// 소유권 이동 (move 사용)
unique_ptr<int> ptr2 = move(ptr1);
if (!ptr1) {
cout << "ptr1은 이제 비어 있습니다." << endl;
}
cout << "ptr2의 값: " << *ptr2 << endl;
return 0;
}
#include <iostream>
#include <memory>
using namespace std;
class MyClass {
public:
MyClass(int val) : value(val) {
cout << "MyClass 생성: " << value << endl;
}
~MyClass() {
cout << "MyClass 소멸: " << value << endl;
}
void display() const {
cout << "값: " << value << endl;
}
private:
int value;
};
int main() {
// unique_ptr로 MyClass 객체 관리
unique_ptr<MyClass> myObject = make_unique<MyClass>(42);
// MyClass 멤버 함수 호출
myObject->display();
// 소유권 이동
unique_ptr<MyClass> newOwner = move(myObject);
if (!myObject) {
cout << "myObject는 이제 비어 있습니다." << endl;
}
newOwner->display();
// 범위를 벗어나면 newOwner가 관리하는 메모리 자동 해제
return 0;
}
#include <iostream>
#include <memory> // shared_ptr 사용
using namespace std;
int main() {
// shared_ptr 생성
shared_ptr<int> ptr1 = make_shared<int>(10);
// ptr1의 참조 카운트 출력
cout << "ptr1의 참조 카운트: " << ptr1.use_count() << endl; // 출력: 1
// ptr2가 ptr1과 리소스를 공유
shared_ptr<int> ptr2 = ptr1;
cout << "ptr2 생성 후 참조 카운트: " << ptr1.use_count() << endl; // 출력: 2
// ptr2가 범위를 벗어나면 참조 카운트 감소
ptr2.reset();
cout << "ptr2 해제 후 참조 카운트: " << ptr1.use_count() << endl; // 출력: 1
// 범위를 벗어나면 ptr1도 자동 해제
return 0;
}
#include <iostream>
#include <memory>
using namespace std;
class MyClass {
public:
MyClass(int val) : value(val) {
cout << "MyClass 생성: " << value << endl; // 출력: MyClass 생성: 42
}
~MyClass() {
cout << "MyClass 소멸: " << value << endl; // 출력: MyClass 소멸: 42
}
void display() const {
cout << "값: " << value << endl; // 출력: 값: 42
}
private:
int value;
};
int main() {
// shared_ptr로 MyClass 객체 관리
shared_ptr<MyClass> obj1 = make_shared<MyClass>(42);
// 참조 공유
shared_ptr<MyClass> obj2 = obj1;
cout << "obj1과 obj2의 참조 카운트: " << obj1.use_count() << endl; // 출력: 2
obj2->display(); // 출력: 값: 42
// obj2를 해제해도 obj1이 객체를 유지
obj2.reset();
cout << "obj2 해제 후 obj1의 참조 카운트: " << obj1.use_count() << endl; // 출력: 1
return 0;
}
#include <iostream>
#include <memory>
using namespace std;
class MyClass {
public:
MyClass(int val) : value(val) {
cout << "MyClass 생성: " << value << endl; // 출력: MyClass 생성: 42
}
~MyClass() {
cout << "MyClass 소멸: " << value << endl; // 출력: MyClass 소멸: 42
}
void display() const {
cout << "값: " << value << endl; // 출력: 값: 42
}
private:
int value;
};
int main() {
// shared_ptr로 MyClass 객체 관리
shared_ptr<MyClass> obj1 = make_shared<MyClass>(42);
// 참조 공유
shared_ptr<MyClass> obj2 = obj1;
cout << "obj1과 obj2의 참조 카운트: " << obj1.use_count() << endl; // 출력: 2
obj2->display(); // 출력: 값: 42
// obj2를 해제해도 obj1이 객체를 유지
obj2.reset();
cout << "obj2 해제 후 obj1의 참조 카운트: " << obj1.use_count() << endl; // 출력: 1
return 0;
}
언리얼엔진의 메모리 관리
언리얼 엔진은 객체들의 메모리 관리를 자동화하기 위해 가비지 컬렉션 시스템을 사용 → 이는 마치 로봇 청소기가 사용하지 않는 물건(메모리)을 알아서 치워주는 것과 같다.
이를 통해 메모리 누수나 dangling pointer 와 같은 오류가 줄어든다.
가비지 컬렉션 - 마크 앤 스윕 알고리즘 방식으로 작동
주기적으로 사용하지 않는 UObject들을 식별하여 제거
- 루트셋에서 시작
- 루트셋에 포함된 객체들을 식별
- 항상 살아있다고 간주되는 특별 객체
- 엔진, 컨트롤러
- 마크 단계
- 사용중인 객체를 마크(표시)함
- 스윕 단계 - 메모리 회수
- 마크 되지 않은 객체들이 차지하고 있던 메모리를 회수 함
가비지컬렉션 동작 방식을 제어하는 플레그들
- RF_RootSet
- 이 플러그가 설정된 객체는 루트셋의 일부로 관리
- 즉, 가비지 컬렉션 대상이 아님. AddToRoot()으로 설정, RemoveFromRoot() 으로 헤제
- RF_BeginDestoryed
- 해당 함수 BeginDestroy() 는 객체가 실제로 메모리에서 해제되기 전에 필요한 정리 작업을 수행하는 함수
- RF_FinishDestoryed
- 해당 함수 FinishDestory() 호출 후 객체의 메모리가 완전히 해제
언리얼 엔진의 리플렉션 시스템
프로그램이 실행 중에 자신의 구조와 상태를 검사하고 수정할 수 있는 능력을 말한다.
리플렉션은 UObject를 위한 운영체제
사용자가 작성한 코드 → 언리얼에서는 이해할 수 없음 → 따라서 Unreal engine tool(UHT) 에서 매크로를 사용해서 설명
매크로
- UCLASS()
- UPROPERTY()
- UFUNCTION()
- USTRUCT()
- GENERATED_BODY()
사용자 정의 객체 → 리플렉션 → 언리얼 엔진 속성을 가진 객체 → 가비지 컬렉션, 에디터 통합, 비주얼 스크립팅, 블루 플린트.
'c++ > 알고리즘' 카테고리의 다른 글
| C++ 알고리즘) 스택 및 큐 (0) | 2026.03.12 |
|---|---|
| C++ 알고리즘) 시뮬레이션 및 행렬 연산 (0) | 2026.03.11 |
| C++ 알고리즘) 정렬 (0) | 2026.03.10 |
| C++ 알고리즘) 벡터, 덱, 및 재귀 함수 (0) | 2026.03.09 |
| C++ 알고리즘) 함수, STL의 기초 및 디자인 패턴 (1) | 2026.03.06 |