728x90
반응형
std::unique_ptr
는C++
에서 단일 소유권을 보장하는 스마트 포인터(smart pointer
)로, 자원 관리와 메모리 해제를 자동으로 처리하여 메모리 누수를 방지하는 데 큰 역할을 합니다.- 다만, 생성 방법과 사용 방법에 따라 예외 상황에서 예상치 못한 문제가 발생할 수 있으므로 주의가 필요합니다.
-
cpp
auto myCellp = std::make_unique<SpreadsheetCell>();
-
make_unique
는C++14
부터 제공되며,- 코드가 간결하고 가독성이 좋습니다.
- 예외 발생 시에도 자원 누수 위험이 없습니다.
- 메모리 할당과 객체 생성이 원자적으로 처리되므로 안전합니다.
-
unique_ptr
를 생성할 때는 항상make_unique
를 사용하는 것이 표준적으로 권장됩니다.
-
cpp
std::unique_ptr<SpreadsheetCell> myCellp(new SpreadsheetCell());
⚠️ 이 방법도 가능하지만,- 예외 안전성이 부족합니다.
- 여러 객체를 순차적으로 생성할 때 중간에 예외가 발생하면 이미 생성된 자원이 누수될 수 있습니다.
-
cpp
#include <iostream> #include <memory> #include <stdexcept> class SpreadsheetCell { public: SpreadsheetCell() { std::cout << "SpreadsheetCell 생성\n"; } ~SpreadsheetCell() { std::cout << "SpreadsheetCell 소멸\n"; } }; class ThrowingConstructor { public: ThrowingConstructor() { std::cout << "ThrowingConstructor 생성\n"; throw std::runtime_error("생성 중 예외 발생!"); } }; int main() { try { // SpreadsheetCell 객체가 먼저 생성되지만 // 다음 줄에서 예외가 발생하면 이미 생성된 자원은 해제되지 않고 누수 발생 std::unique_ptr<SpreadsheetCell> ptr1(new SpreadsheetCell()); ThrowingConstructor obj; // 예외 발생 // ptr1이 스택에 완전히 초기화되기 전에 예외가 발생하면서 소멸자가 호출되지 않음 } catch (const std::exception& e) { std::cout << "예외 잡음: " << e.what() << "\n"; } return 0; }
- 👉 이런 문제를 피하려면
make_unique
를 사용하는 것이 좋습니다.
-
cpp
SpreadsheetCell* rawPtr = new SpreadsheetCell(); std::unique_ptr<SpreadsheetCell> myCellp(rawPtr);
⚠️ 이 방법은 가능하지만 위험합니다.rawPtr
이 다른 코드에서 소유권을 중복해서 참조하고 있을 경우 문제가 발생합니다.- 같은 포인터를 두 번
delete
하는 잘못된 동작이나, 소유권 혼동으로 인한 버그로 이어질 수 있습니다. - 또한
unique_ptr
생성 직후raw pointer
를 다시 사용하려는 경우 프로그램 오류나undefined behavior
를 초래합니다.
- 👉 따라서
raw pointer
를unique_ptr
로 감싸는 방법은- 소유권 이전의 의도가 명확하고, 다른 곳에서 해당 포인터를 절대 참조하지 않을 때만 사용 해야 하며,
- 일반적으로는 권장하지 않습니다.
-
방법 장점 단점 및 주의사항 std::make_unique
사용안전함, 간결함, 예외 발생 시에도 누수 없음 가장 추천되는 표준적 방법 new
연산자 직접 사용코드상에서 메모리 할당이 명확히 보임 예외 발생 시 자원 누수 가능성이 있으며, 특별한 상황이 아니면 지양 권장 이미 생성된 raw pointer
감싸기기존 raw pointer
를 이전할 때 사용할 수 있음소유권 혼동 및 중복 해제 위험이 있으며, 꼭 필요한 상황 외에는 권장하지 않음
- 📌 결론적으로
std::make_unique
를 사용하는 것이 가장 안전하며, - 특수한 상황(생성자가
protected
이거나, 복잡한 초기화 과정이 필요한 경우 등)을 제외하고는new
연산자 직접 사용과raw pointer
감싸기는 피하는 것이 좋습니다.
- 도움이 되셨으면 하단의 ❤️ 공감 버튼 부탁 드립니다. 감사합니다! 😄
728x90
반응형
'C C++' 카테고리의 다른 글
C++에서 구조체(struct)를 다양하게 선언하는 방법 (0) | 2025.03.21 |
---|---|
C++11과 C++14에서 std::unique_ptr 배열 사용법 비교 (0) | 2025.03.20 |
C++ 문자열(string)을 실수형 double로 변환하는 다양한 방법 (0) | 2025.03.20 |
C++ 컴파일러의 최대 잘라먹기(Maximal Munch) 원칙과 주의할 사례 (0) | 2025.03.20 |
C++ 멤버 변수(member variable)와 멤버 함수 매개변수(member function parameter) 이름 충돌 문제 (0) | 2025.03.20 |