15.5 std::unique_ptr
unisque_ptr : 포인터가 가리키고있는 데이터의 소유권이 한 곳에만 속할 경우 쓰는 스마트 포인터
#include <iostream>
#include <memory>
#include "Resource.h"
auto doSomething()
{
return std::unique_ptr<Resource>(new Resource(5));
}
void doSomething2(std::unique_ptr<Resource> & res)
{
res->setAll(10);
}
using namespace std;
int main()
{
{
//Resource *res = new Resource(10000000);
std::unique_ptr<Resource> res(new Resource(10000000)); // delete이 없지만 스스로 destructor 호출
//delete res;
}
return 0;
}
#include <iostream>
#include <memory>
#include "Resource.h"
auto doSomething()
{
return std::unique_ptr<Resource>(new Resource(5));
}
//void doSomething2(std::unique_ptr<Resource> & res)
//{
// res->setAll(10);
// res->print();
//return res
//}
void doSomething2(Resource *res)
{
res->setAll(100);
res->print();
}
using namespace std;
int main()
{
{
std::unique_ptr<int> upi(new int);
auto *ptr = new Resource(5);
//std::unique_ptr<Resource> res1(ptr);
std::unique_ptr<Resource> res1(new Resource(5));
//auto res1 = std::make_unique<Resource>(5);
//auto res1 = doSomething(); // 초기화 방법
res1->setAll(5);
res1->print();
std::unique_ptr<Resource> res2;
std::cout << std::boolalpha;
std::cout << static_cast<bool>(res1) << "\n"; // nullptr이 아님 => True
std::cout << static_cast<bool>(res2) << "\n"; // res2는 갖고있는게 없으므로 nullptr => False
// res2 = res1; // unique_ptr은 복사가 안된다. 소유권이 유일하기 때문.
res2 = std::move(res1);
std::cout << std::boolalpha;
std::cout << static_cast<bool>(res1) << "\n";
std::cout << static_cast<bool>(res2) << "\n";
if (res1 != nullptr) res1->print();
if (res2 != nullptr) res2->print(); // (*res2).print();
}
return 0;
}
출력
Resource length constructed
5 5 5 5 5
true
false
false
true
5 5 5 5 5
Resource destroyed
다른 예제
#include <iostream>
#include <memory>
#include "Resource.h"
auto doSomething()
{
return std::unique_ptr<Resource>(new Resource(5));
}
//void doSomething2(std::unique_ptr<Resource> & res)
//{
// res->setAll(10);
// res->print();
//return res
//}
void doSomething2(Resource *res)
{
res->setAll(100);
res->print();
}
using namespace std;
int main()
{
{
auto res1 = std::make_unique<Resource>(5);
res1->setAll(1);
res1->print();
//doSomething2(res1); // 컴파일이 안된다. res1은 copy가 안되니까 l-value reference로 받으면 안된다. (&일 때)
doSomething2(std::move(res1)); // 이렇게 하면 res1은 nullptr이 된다.
// 만약 res1을 다시 사용하고 싶다면 return res를 하면 된다.
doSomething2(res1.get()); // unique_ptr의 get함수. resource의 포인터를 가져오는 함수. l-value reference처럼 작동.
res1->print();
}
return 0;
}
다른 예제
#include <iostream>
#include <memory>
#include "Resource.h"
auto doSomething()
{
return std::unique_ptr<Resource>(new Resource(5));
}
//void doSomething2(std::unique_ptr<Resource> & res)
//{
// res->setAll(10);
// res->print();
//return res
//}
void doSomething2(Resource *res)
{
res->setAll(100);
res->print();
}
using namespace std;
int main()
{
{
Resource *res = new Resource;
std::unique_ptr<Resource> res1(res);
std::unique_ptr<Resource> res2(res); // 이렇게 사용하면 안됨. 소유권은 반드시 하나
delete res; // 두번 지우려고 하니 문제가 생김.
}
return 0;
}