std::unique_ptr属于STL库,它的作用和auto_ptr相似,也是管理一个对象指针,提供一个释放内存的封装操作。
顾名思义,std::unique_ptr独有对象指针的管理权,不会允许其他unique_ptr再来分享了,这是和std::auto_ptr最大的区别了,也是比auto_ptr优越的地方了。
std::auto_ptr有两个成员变量(Template parameters):
1.管理对象的指针。
2.内存回收对象(callable object used as deleter)。默认为default_delete。
std::uniqur_ptr的构造函数有多个:
default (1) |
constexpr unique_ptr() noexcept;
|
from null pointer (2) |
constexpr unique_ptr (nullptr_t) noexcept : unique_ptr() {}
|
from pointer (3) |
explicit unique_ptr (pointer p) noexcept;
|
from pointer + lvalue deleter (4) |
unique_ptr (pointer p,
typename conditional::value,D,const D&> del) noexcept;
|
from pointer + rvalue deleter (5) |
unique_ptr (pointer p,
typename remove_reference::type&& del) noexcept;
|
move (6) |
unique_ptr (unique_ptr&& x) noexcept;
|
move-cast (7) |
template
unique_ptr (unique_ptr&& x) noexcept;
|
move from auto_ptr (8) |
template
unique_ptr (auto_ptr&& x) noexcept;
|
copy (deleted!) (9) |
unique_ptr (const unique_ptr&) = delete; |
可以指定构造对象,同时支持move构造:
std::unique_ptr GetVal()
{
std::unique_ptr pLocalValue(new int(10));
return pLocalValue;
}
int main()
{
std::unique_ptr pMoveConstruct = GetVal();
return 0;
}
但是它不支持拷贝构造,所以就不会出现像std::auto_ptr那么容易的所有权转移问题了。
std::unique_ptr同样会出现同时持有同一对象指针的所有权问题:
int* pTemp = new int();
std::unique_ptr p1(pTemp);
std::unique_ptr p2(pTemp);
所以也要保证"防止两个unique_ptr拥有一个对象"。
std::unique_ptr不支持拷贝构造,所以不能直接作为容器元素,但是我们可以通过move构造来创建容器元素:
std::unique_ptr pTemp(new int());
std::vector < std::unique_ptr > vecTest;
vecTest.push_back(std::move(pTemp));
同时,std::unique_ptr重载了=操作符:
move assignment (1) |
unique_ptr& operator= (unique_ptr&& x) noexcept;
|
assign null pointer (2) |
unique_ptr& operator= (nullptr_t) noexcept;
|
type-cast assignment (3) |
template
unique_ptr& operator= (unique_ptr&& x) noexcept;
|
copy assignment (deleted!) (4) |
unique_ptr& operator= (const unique_ptr&) = delete; |
我们可以看到,同样的只支持move赋值:
std::unique_ptr pTest1(new int());
std::unique_ptr pTest2 = std::move(pTest1);
另外还有operator bool操作符,它实现了和指针同样的操作,可以直接当做bool来进行指针的判断:
std::unique_ptr pTest1(new int());
if (pTest1) //do sth
std::unique_ptr和std::auto_ptr的另外一个区别就是可以管理数组,同时也实现了operator[]:
std::unique_ptr pTest1(new int[10]);
for (int i = 0; i < 10; ++i)
{
pTest1[i] = 10;
}
我们和std::auto_ptr来对比的话可以发现std::unique_ptr和std::auto_ptr非常的相似,但是unique_ptr不能随随便便的转移所有权,必须通过move来转移,这样对于语意理解有莫大的好处,也不会存在莫名其妙感了。
2016-10-09:
今天在使用unique_ptr的时候发现一个问题,因为看到有一个release的成员方法,就想当然的认为是释放持有指针的内存,但实际发现析构函数怎么都进不去,重新看文档发现只是释放了所有权并且返回所持有对象的指针。