질문 배경:
일반(원시) 포인터는 C++에서 동적 메모리 작업을 위한 전통적인 메커니즘입니다. 이 기법은 범용적이며 추상적이지만 불행히도 메모리 누수, 이중 삭제, 댕글링 포인터 오류와 같은 여러 오류에 매우 취약합니다. 그래서 C++11부터는 표준 라이브러리에 메모리 수명 관리를 자동으로 수행하는 스마트 포인터 템플릿 클래스(std::unique_ptr, std::shared_ptr, std::weak_ptr)가 포함되었습니다.
문제:
일반 포인터를 사용할 때 메모리 할당 및 해제에 대한 책임이 프로그래머에게 있습니다. 메모리 해제에서의 오류는 메모리 누수, 데이터 손상 및 프로그램 충돌로 이어질 수 있습니다. 예외 처리 또는 다른 함수에 포인터를 전달할 때 복잡한 경우가 특히 발생합니다.
해결책:
스마트 포인터는 할당된 메모리를 캡슐화하고 더 이상 소유자가 없을 때 자동으로 해제합니다. 이들은 RAII를 구현합니다. std::unique_ptr는 독점 소유권을 제공하고, std::shared_ptr는 공유 소유권을 제공하며, std::weak_ptr는 "참조 순환"을 방지하기 위해 제어되지 않는 소유권을 제공합니다.
코드 예:
#include <memory> void foo() { std::unique_ptr<int> p = std::make_unique<int>(5); // 예외 발생 시에도 메모리가 해제됩니다 // ... }
주요 특징:
std::unique_ptr를 배열에 사용 할 수 있습니까? (new[]로 생성된 배열에서)
아니요, 배열의 경우 std::unique_ptr<T[]>를 사용해야 합니다: 이 경우 delete[]가 호출됩니다.
std::unique_ptr<int[]> arr(new int[10]);
표준 스마트 포인터가 모든 메모리 누수를 방지할 수 있습니까?
아니요. 예를 들어, std::shared_ptr 간의 순환 참조는 메모리 누수로 이어질 수 있습니다. 이러한 순환을 끊기 위해 std::weak_ptr를 사용합니다.
스마트 포인터가 동일한 객체를 두 번 "삭제"할 수 있습니까?
아니요, 소유권 논리를 위반하지 않는 경우(원시 포인터를 사용하지 않는 경우) 그렇지 않습니다! 원시 포인터를 수동으로 복사하면 두 번 삭제가 발생할 수 있습니다.
원시 포인터가 사용되고 수동으로 메모리가 해제되며, 예외 발생 시 메모리가 해제되지 않습니다.
장점:
단점:
std::unique_ptr 및 std::make_unique를 사용하여 객체를 생성하고 함수를 통해 전달합니다.
장점:
단점: