当需要使用智能指针时,std::unique_ptr(独占式指针)基本上应当是首选,因为默认情况下std::unique_ptr和裸指针有着相同的尺寸,且因为执行的是移动操作,所以效率也非常高,另外对于大多数的操作(包括提领),他们都是精确的执行了相同的指令。
std::unique_ptr实现的是专属所有权语义,其只支持移动,不支持复制,也不能将一个裸指针直接赋值给std::unique_ptr对象,因为编译器禁止这种隐式转换。
默认的std::unique_ptr的析构函数将调用delete完成指针删除操作,当然,如果默认的析构函数不满足要求,我们也可以自定义析构函数,例如:
class MyTest {
public:
//自定义类构造函数
MyTest() {
cout << "MyTest" << endl;
};
//自定义类析构函数
~MyTest() {
cout << "~MyTest" << endl;
};
};
int main()
{
{
//std::unique_ptr的自定义析构函数,t可以为MyTest类型及其子类
auto MyDelete = [](MyTest* t) {
cout << "MyDelete" << endl;
delete t;
};
//智能指针初始化
std::unique_ptr<MyTest,decltype(MyDelete)> p(new MyTest, MyDelete);
}
return 0;
}
但我们也应该知道,使用std::unique_ptr自定义析构函数时,std::unique_ptr的尺寸会有所增加,增加的尺寸与函数对象存储的状态个数有关,一般情况下,相对于函数,无捕获的lambda表达式是更好的自定义析构函数的选择。析构器也属于std::unique_ptr型别的组成部分,只要析构器相同的变量之间,才能进行移动。
另外,std::unique_ptr以两个形式提供,一种是单个对象(std::unique_ptr<T>),另一种则是数组(std::unique_ptr<T[]>),std::unique_ptr对两种形式提供的成员函数有所不同,例如,对单个对象形式不提供索引运算符(operator[]),对数组形式不提供提领运算符(operator*和operatpr->)。
最后一点,std::unique_ptr可以很方便的转换为std::shared_ptr型别,但反之则不行。例如:
//可以将std::unique_ptrz转换为std::shared_ptr
std::unique_ptr<int> u(new int);
std::shared_ptr<int> p = std::move(u);
//不可以std::shared_ptr转换为std::unique_ptr
std::shared_ptr<int> u(new int);
std::unique_ptr<int> p = std::move(u);