《C++ Primer》P400
为了更容易(同时更安全)地使用动态内存,新的标准提供了智能指针(smart pointer)类型来管理动态对象。
智能指针的行为类似常规指针,重要的区别是它负责自动释放所指向的对象。
shared_ptr允许多个指针指向同一个对象
创建并初始化一个shared_ptr智能指针的方式有四种:
1.默认初始化
2.make_shared
3.new返回的指针
4.其他类型的资源的指针(非动态内存)
shared_ptr p;//可以指向int的一个空指针,指针值为空
《C++ Primer》P401
此函数再动态内存中分配一个对象,使用args初始化此对象,返回一个指向此对象的shared_ptr
调用形式:make_shared
(args) 这里的args可以是空、字面值常量、变量、能与T类型的某个构造函数相匹配的参数列表等。
shared_ptr p0=make_shared();//指向一个默认值初始化的int对象,此对象值为0
shared_ptr p1=make_shared(42);//指向一个值为42的int
int a = 10;
shared_ptr p2=make_shared(a);//使用a初始化一个动态分配的类型为int的对象,注意这个对象和a不是同一个对象
注意:这个对象和a不是同一个对象,这个对象是make_shared函数在动态内存中分配出来的一个对象,使用a进行值初始化,所以这个对象的值和a的值是相等的,但不是同一块内存!!!
shared_ptr p3=make_shared(10,'9');//指向一个值为“9999999999”的string
我们可以用new返回的指针来直接初始化智能指针:
shared_ptr p(new int(42));//p指向一个值为42的int对象
注意:接受指针参数的智能指针构造函数是explicit的,因此我们不能将一个内置指针隐式转换为一个智能指针,必须使用直接初始化形式!!!
shared_ptr p = new int(42));//错误,必须使用直接初始化
//error C2440: “初始化”: 无法从“int *”转换为“std::shared_ptr”,普通指针不能直接赋值给智能指针
《C++ Primer》P412
默认情况下,一个用来初始化智能指针的普通制作必须指向动态内存,因为智能指针默认使用delete释放它所关联的对象。
当然,我们可以将智能指针绑定到一个指向其他类型的资源的指针上,但是,为了这样做,必须提供自己的操作来替代delete
默认使用delete,可以将普通指针绑定到智能指针上。智能指针由普通指针值初始化,prob.get()的值等于&a 和pb的值
int a = 10;
int *pb = &a;//普通指针,指向a对象
std::shared_ptr ptrb(&a);//默认使用delete
std::shared_ptr ptrb(pb);//默认使用delete
这里是因为我使用的是内置类型int的指针,默认delete刚好可以释放int类型,如果是其他类型的资源,必须加上自定义的删除器
所以,完整的写法应该由如下所示:
int a = 10;
int *pb = &a;//普通指针,指向a对象
std::shared_ptr ptrb(&a, [](int *x) {delete x; });//定义了lambda作为删除器
std::shared_ptr ptrb(pb,[](int *x) { delete x; });//定义了lambda作为删除器
这里的lambda表达式 [](int *x) { delete x; } 等价于 delete
如果使用的string类型的数组的指针(也就是string*指针)创建shared_ptr,则:
string *pia = new string[10];
//delete[] pia;//正确,当 new 一个有析构函数的对象数组的时候 必须要用 delete[]删除
//delete pia;//错误
shared_ptrsp(pia, [](string *p) {delete[] p; });//正确
//shared_ptrsp(pia);//错误
//shared_ptrsp(pia, [](string *p) {delete p; });//错误
这里的lambda表达式 [](string *p) { delete[] x; } 作为string*类型的删除器,
换句话说,这个删除器能够完成对shared_ptr中保存的指针进行释放操作