当需要使用智能指针时,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<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);
要点速记
- std::unique_ptr是小巧,高速的,具备只移型别的智能指针,对托管资源实施专属所有权语义
- 默认的,std::unique_ptr资源析构采用delete运算符实现,但可以指定自定义删除器。有状态的删除器和采用函数指针实现的删除器都会增加std::unique_ptr的尺寸。
- 可以将std::unique_ptr轻松转换为std::shared_ptr,但是无法将std::shared_ptr转换为std::unique_ptr