在这篇文章中我主要探讨下std::unique_ptr
这个智能指针,说到智能指针就需要说下它和原始指针的区别了,原始指针很灵活但是处处都是陷阱,用不好很容易出错,但是智能指针(Smart Pointer)相比于原始指针更易用,通过RAII
机制和引用计数机制来管理指针指向的资源,本文谈论是就是C++11
提供的智能指针中的一个std::unique_ptr
,根据本文的题目可知,这是一个excluseive-ownership
,也就是所有权独享的智能指针,它的所有权只能转移,不能像shared_ptr
那样可以共享所有权。
上面说到了std::unique_ptr
的所有权问题,接下来谈论下另外一个问题就是占用内存大小的问题,std::unique_ptr
相比于其它智能指针来说有一个得天独厚的优点就是占用内存小,几乎和原始指针一样,通过std::unique_ptr
来执行方法的开销和通过原始指针来执行方法的开销一样。但是有一种情况会导致std::unique_ptr
的大小变大,就是需要自定义删除器的时候,下面具体来分析下这种特殊情况。
int main() {
int *p;
std::unique_ptr<int> ps(new int(6));
std::cout << sizeof(p) << ":" << sizeof(ps) << std::endl;
return 0;
}
在64位系统上,上面的代码会输出8:8
因为std::unique_ptr
几乎不需要在内部维护什么状态,所以它的大小和原始指针是一样大的,而shared_ptr
因为内部需要维护引用计数,因此其大小肯定是大于原始指针的。默认情况下当unique_ptr
离开作用域后会导致调用默认的删除器,删除其指向的资源。默认的删除器很简单就是直接调用delete
,这几乎是不需要在内部维护这样的信息的,只有当用户自定义删除器的时候才会在内部保存自定义的删除器,因此这也导致了占用的内存变大了(无状态的函数对象和没有捕捉参数的lambda表达式不会导致内存变大)。
int main() {
int c = 2;
// 带参数捕捉的lambda表达式,会导致unique_ptr占用内存变大
auto delint = [=](int *p) {
std::cout << c << std::endl;
delete p;
};
std::unique_ptr<int, decltype(delint)> p(new int(10), delint);
// 输出16
std::cout << sizeof(p) << std::endl;
return 0;
}
最后介绍一些std::unique_ptr
的杂项作为本文的结束,第一个是std::unique_ptr
对数组的支持,和shared_ptr
不一样的是,unique_ptr
支持T[]
,相应的在删除的时候会自动调用delete []
来删除资源。第二个是std::unique_ptr
可以很轻松的转换为std::shared_ptr
,可以直接隐式转换。