智能指针注意的坑

1.同一普通指针不能同时为多个 shared_ptr 对象赋值,否则会导致程序发生异常。例如:

int* ptr = new int;
std::shared_ptr<int> p1(ptr);
std::shared_ptr<int> p2(ptr);//错误. 容易引起double delete

原因是这个地址容易引起 double delete 懂的吧

 

2 在初始化 shared_ptr 智能指针时,还可以自定义所指堆内存的释放规则,这样当堆内存的引用计数为 0 时,会优先调用我们自定义的释放规则。
在某些场景中,自定义释放规则是很有必要的。比如,对于申请的动态数组来说,shared_ptr 指针默认的释放规则是不支持释放数组的,只能自定义对应的释放规则,才能正确地释放申请的堆内存。

//指定 default_delete 作为释放规则 
std::shared_ptr<int> p6(new int[10], std::default_delete<int[]>());
对于申请的动态数组,释放规则可以使用 C++11 标准中提供的 default_delete<T> 模板类外,我们也可以自定义释放规则:如下
//自定义释放规则 void deleteInt(int*p) { //也可以写成lamd 表达式 delete []p; } //初始化智能指针,并自定义释放规则 std::shared_ptr<int> p7(new int[10], deleteInt);

//也可以写成lamd 表达式

std::shared_ptr<int> p7( new int[10], [](int* p) {delete[]p;} );

 某些特殊场景必须要自己自定义  delete 函数 传进shared_ptr 中去 如下:

int a = 10;
int *pb = &a;//普通指针,指向a对象
std::shared_ptr<int> ptrb(&a);//默认使用delete 
std::shared_ptr<int> ptrb(pb);//默认使用delete 

int a = 10;
int *pb = &a;//普通指针,指向a对象
std::shared_ptr<int> ptrb(&a, [](int *x) {delete x; });//定义了lambda作为删除器
std::shared_ptr<int> ptrb(pb,[](int *x) { delete x; });//定义了lambda作为删除器


string *pia = new string[10];
//delete[] pia;//正确,当 new 一个有析构函数的对象数组的时候 必须要用 delete[]删除
//delete pia;//错误

shared_ptr<string>sp(pia, [](string *p) {delete[] p; });//正确
//shared_ptr<string>sp(pia);//错误
//shared_ptr<string>sp(pia, [](string *p) {delete p; });//错误

 踩坑【错误1】试图从raw指针隐式转换到智能指针

shared_ptr<Rect> p5 = new Rect(r_points, r_width, r_height); // !!!

 【错误2】将非动态分配的内存托管给智能指针

Rect rect_6(r_points, r_width, r_height);
shared_ptr<Rect> p6(&rect_6); // !!!  将栈 变量用初始化智能指针肯定不对哈

 【错误3】将同一份动态内存托管给多个智能指针

Rect *xx = new Rect(r_points, r_width, r_height);
shared_ptr<Rect> p7(xx);
{
    shared_ptr<Rect> p8(xx); // !!!
    shared_ptr<Rect> p9(p7.get()); // !!!
}
xx = nullptr;
Rect rect_7 = *p7;

 

《Cpp Primer》中提到几条基本规范,建议严格遵循: 1.不使用相同的raw指针初始化(或reset)多个智能指针。 2.不delete get()返回的指针。 3.不使用get()初始化或reset另一个智能指针。 4.如果你使用get()返回的指针,记住当最后一个对应的智能指针销毁后,你的指针就变为无效了。 5.如果你使用智能指针管理的资源不是new分配的内存,记住传递给它一个删除器。

 

 

 

 3 智能指针初始化 要注意 应为 shared_ptr等智能指针 构造函数是 explicit 显示的构造函数不能用 指针隐式转换

// 我们可以用new返回的指针来直接初始化智能指针:
shared_ptr<int> p(new int(42));//p指向一个值为42的int对象

//注意:接受指针参数的智能指针构造函数是explicit的,因此我们不能将一个内置指针隐式转换为一个智能指针,必须使用直接初始化形式!!!
shared_ptr<int> p = new int(42));//错误,必须使用直接初始化
//error C2440: “初始化”: 无法从“int *”转换为“std::shared_ptr<int>”,普通指针不能直接赋值给智能指针

 

 

 <深入应用c++11> 也有一些总结

 

 

 

 

 ====================================================================================================

 

Effective Modern C++ 之 优先选用make_unique和make_shared  还没理解下次总结

 

make_shared 使用:

此函数再动态内存中分配一个对象,使用args初始化此对象,返回一个指向此对象的shared_ptr

调用形式:make_shared<T>(args)

这里的args可以是空字面值常量变量、 能与T类型的某个构造函数相匹配的参数列表等

1)空
//指向一个默认值初始化的int对象,此对象值为0
shared_ptr<int> p0=make_shared<int>();
2)字面值常量 
//指向一个值为42的int
shared_ptr<int> p1=make_shared<int>(42);
3)变量
//使用a初始化一个动态分配的类型为int的对象,注意这个对象和a不是同一个对象  注意:  这个对象和a不是同一个对象,这个对象是make_shared函数在动态内存中分配出来的一个对象,使用a进行值初始化,所以这个对象的值和a的值是相等的,但不是同一块内存!!!
int a = 10;
shared_ptr<int> p2=make_shared<int>(a);
4)能与T类型的某个构造函数相匹配的参数列表
//指向一个值为“9999999999”的string
shared_ptr<int> p3=make_shared<string>(10,'9');

 

posted on 2021-11-29 12:03  zhangkele  阅读(622)  评论(0编辑  收藏  举报

导航