auto_ptr
#include <memory>
auto_ptr<double> ap(new double);
*ap = 25.5;
- memory헤더 파일을 소스코드에 포함해야한다.
- 메모리가 해제될 때 ap를 해제하고 ap의 파괴자가 동적메모리를 해제한다.
- new로 생성한 단일 객체에 대해서만 메모리의 해제를 보장한다.
- 동일한 메모리 위치를 가리키는 객체를 2개 이상 생성하지 않아야 한다는 점입니다.
- C++11이 지원되는 환경이라면 auto_ptr을 완전히 대체하는 unique_ptr을 사용하면 됩니다.
auto_ptr<double> ap(new double);
auto_ptr<double> ap2;
*ap = 25.5;
ap2 = ap;
cout << *ap;
- 다음과 같을 때 ap는 ap2에 소유권을 넘기게된다. 더 안전하다고 할 수 있다.
unique_ptr
unique_ptr<double> ap(new double);
unique_ptr<double> ap2;
*ap = 25.5;
ap2 = ap; //애초에 컴파일에러
cout << *ap;
unique_ptr<double[]> ap3(new double(5));
ap3[0] = 2;
unique_ptr<MyClass> ap4 = make_unique<MyClass>();
- unique_ptr은 단일 소유권을 가진 스마트 포인터로, 소유권을 가진 유일한 스마트포인터가 소멸될 때 자원을 해제합니다.
- 복사는 허용하지 않는다.
- 이동은 가능하다.
- 널이 아닐 때에 소멸시에 자신이 가리키는 자원을 파괴한다.
- 다른 스마트포인터와는 다른 점으로 array로도 사용할 수 있다.
unique_ptr<string> demo(const char * s)
{
unique_ptr,string> temp(new string(s));
return temp;
}
unique_ptr<string> ps;
ps = demo("Uniquely special");
- 다음과같이 함수를 통해 임시 unique_ptr을 리턴하면 ps는 unique_ptr이 리턴한 객체의 소유권을 얻는다.
- 이렇게 되면 소유권 문제를 해결할 수 있다.
- 유효하지 않은 값에 접근할 가능성이 없어진다.
#include <iostream>
#include <memory>
class MyClass {
public:
MyClass() {
std::cout << "MyClass created" << std::endl;
}
~MyClass() {
std::cout << "MyClass destroyed" << std::endl;
}
};
int main() {
std::unique_ptr<MyClass> uniquePtr = std::make_unique<MyClass>();
// unique_ptr을 shared_ptr로 이동
std::shared_ptr<MyClass> sharedPtr = std::move(uniquePtr);
if (!uniquePtr) {
std::cout << "uniquePtr is now empty" << std::endl;
}
if (sharedPtr) {
std::cout << "sharedPtr now owns the MyClass instance" << std::endl;
}
return 0;
}
- move()를 사용하여 shared_ptr에도 대입가능하다.
shared_ptr
shared_ptr<double> ap(new double);
shared_ptr<double> ap2;
*ap = 25.5;
ap2 = ap;
cout << *ap;
- shared_ptr는 참조를 하게 될 경우 참조카운트를 추가한다. 처음 ap에서 1, ap2에서 같은 객체를 가르킬 때 2로 올라간다.
- reference counting(참조 카운트) 방식으로 객체의 소유권을 공유하게 되며 이 카운트가 0이 되면 객체가 해제됩니다.
- shared_ptr의 객체는 복사가 가능합니다.
- 생포인터도 해당 shared_ptr를 가르킬 수 있지만 shared_ptr이 모두 해제되어 객체가 소멸됐다면 생포인터는 더 이상 nullptr이나 정확한 주소를 가르키고 있지 않고 잘못된 주소를 가르킵니다. 이 경우를 댕글링포인터라고 합니다.
- shared_ptr를 가진 객체가 서로 상호 참조하고 있다면 순환참조를 하게 되어서 카운트가 1이하로 떨어지지않아 삭제되는 문제가 있습니다. 해당 문제를 해결하기 위해서 weak_ptr를 사용합니다.
weak_ptr
#include <iostream>
#include <memory>
class MyClass {
public:
MyClass(int value) : value(value) {
std::cout << "MyClass created with value: " << value << std::endl;
}
~MyClass() {
std::cout << "MyClass destroyed" << std::endl;
}
int value;
};
int main() {
std::shared_ptr<MyClass> sharedPtr = std::make_shared<MyClass>(42);
std::weak_ptr<MyClass> weakPtr = sharedPtr;
// Before shared_ptr is reset
if (auto lockedPtr = weakPtr.lock()) {
std::cout << "Locked value: " << lockedPtr->value << std::endl;
} else {
std::cout << "The object has been destroyed" << std::endl;
}
sharedPtr.reset(); // Destroy the shared pointer
// After shared_ptr is reset
if (auto lockedPtr = weakPtr.lock()) {
std::cout << "Locked value: " << lockedPtr->value << std::endl;
} else {
std::cout << "The object has been destroyed" << std::endl;
}
return 0;
}
weak_ptr : shared_ptr과 함께 사용되어 순환 참조를 방지하고 메모리 누수를 방지하기 위해 사용되는 스마트 포인터입니다.
- shared_ptr의 약한 참조를 제공하므로 shared_ptr의 참조 카운트를 증가시키지 않습니다.
- weak_ptr은 shared_ptr으로 참조되는 객체의 유효성을 검사하고, 객체에 접근할 때 **std::lock()**을 사용하여 안전하게 참조합니다. (참조된 주소가 lock())
- weak_ptr이 참조하고 있는 메모리가 해제되었을 때 해당 주소는 잘못된 주소를 가르키지만 lock()을 통해서 안전하게 shared_ptr을 가르키고 있는지 아니면 잘못되거난 빈주소라면 nullptr을 가르키도록 되어 있습니다.
도움사이트 : https://psychoria.tistory.com/42
'C++ > Basic' 카테고리의 다른 글
[C++] 가상함수에 대해 (0) | 2024.05.26 |
---|---|
함수 오버로딩 (0) | 2021.09.17 |
vector와 list의 차이점 (0) | 2021.09.16 |
[C++] new와 malloc의 차이 (0) | 2021.09.15 |
[C++] 가변인자 템플릿 (0) | 2021.08.25 |