unique_ptr
unique_ptr
예제
main.cpp
#include <iostream>
#include <memory>
#include "Resource.h"
using namespace std;
int main()
{
std::unique_ptr<Resource> res(new Resource(100000000));
}
/* stdout
Resource length constructed
Resource destoryed
*/
Resource.h
#pragma once
#include <iostream>
class Resource
{
public:
int *data_ = nullptr;
unsigned length_ = 0;
Resource()
{
std::cout << "Resource default constructed\n";
}
Resource(unsigned length)
{
std::cout << "Resource length constructed\n";
init(length);
}
Resource(const Resource& res)
{
std::cout << "Resource copy constructed\n";
init(res.length_);
for (unsigned i = 0; i < length_; ++i)
data_[i] = res.data_[i];
}
~Resource()
{
std::cout << "Resource destoryed\n";
if (data_ != nullptr) delete[] data_;
}
void init(unsigned length)
{
data_ = new int[length];
length_ = length;
}
Resource& operator = (Resource& res)
{
std::cout << "Resource copy assignment\n";
if (&res == this) return *this;
if (data_ != nullptr) delete[] data_;
init(res.length_);
for (unsigned i = 0; i < length_; ++i)
data_[i] = res.data_[i];
return *this;
}
void print()
{
for (unsigned i = 0; i < length_; ++i)
std::cout << data_[i] << ' ';
std::cout << std::endl;
}
void setAll(const int& v)
{
for (unsigned i = 0; i < length_; ++i)
data_[i] = v;
}
};
make_unique
copy constructor
도 delete
한 상태임을 보여주는 예제
main.cpp
#include <iostream>
#include <memory>
#include "Resource.h"
using namespace std;
auto doSomething(std::unique_ptr<Resource> res) // 에러
{
res->setAll(10);
}
int main()
{
auto res1 = std::make_unique<Resource>(5);
res1->setAll(1);
res1->print();
doSomething(res1);
res1->print();
}
error C2280: 'std::unique_ptr<Resource,std::default_delete<Resource>>::unique_ptr(const std::unique_ptr<Resource,std::default_delete<Resource>> &)': attempting to reference a deleted function
- 에러 메시지를 통해 라이브러리에서 복사 생성자(copy constructor)를
delete
한 것임을 알 수 있다.
이 예제에서 doSomething(std::move(res1))
과 같이 R-value
로 넘기면, doSomething
함수 내부로 unique_ptr
인 res1
이 옮겨간다.
main.cpp
#include <iostream>
#include <memory>
#include "Resource.h"
using namespace std;
auto doSomething(std::unique_ptr<Resource> res)
{
res->setAll(10);
}
int main()
{
auto res1 = std::make_unique<Resource>(5);
res1->setAll(1);
res1->print();
cout << boolalpha << static_cast<bool>(res1) << endl;
doSomething(std::move(res1));
cout << static_cast<bool>(res1) << endl;
}
/* stdout stderr
Resource length constructed
1 1 1 1 1
true
Resource destoryed
false
*/
get()
unique_ptr
로 가지고 있는 포인터를 반환한다.
<memory>
// STRUCT TEMPLATE _Get_deleter_pointer_type
template <class _Ty, class _Dx_noref, class = void>
struct _Get_deleter_pointer_type { // provide fallback
using type = _Ty*;
};
...
template <class _Ty, class _Dx /* = default_delete<_Ty> */>
class unique_ptr {
public:
using pointer = typename _Get_deleter_pointer_type<_Ty, remove_reference_t<_Dx>>::type;
...
_NODISCARD pointer get() const noexcept {
return _Mypair._Myval2;
}
...
private:
template <class, class>
friend class unique_ptr;
_Compressed_pair<_Dx, pointer> _Mypair;
};
<xmemory>
template <class _Ty1, class _Ty2, bool = is_empty_v<_Ty1> && !is_final_v<_Ty1>>
class _Compressed_pair final : private _Ty1 { // store a pair of values, deriving from empty first
public:
_Ty2 _Myval2;
...
};