C ++ 11スマートポインター研究ノート

shared_ptr<int> makes(int value) {
    shared_ptr<int> p2 = make_shared<int>(100);
    shared_ptr<string> p3 = make_shared<string>("hello");
    shared_ptr<int> p4 = make_shared<int>();
    p4 = make_shared<int>(400);
    auto p5 = make_shared<string>(5, 'a');
    return shared_ptr<int>(new int(value));
}

//void myfunc(shared_ptr<int> ptr) //此情况引用计数加1,函数运行完会释放,则减1
void myfunc(shared_ptr<int> &ptr) //引用不会计数器加1
{
    return;
}

shared_ptr<int> myfunc2(shared_ptr<int> &ptr) {
    return ptr;
}

void myDelete(int *p) {
    delete p;
}

//用函数模板来封装shared_ptr数组
template<typename T>
shared_ptr<T> my_shared_array(int size) {
    return shared_ptr<T>(new T[size], default_delete<T[]>());
}

//int main()
//{
//    //shared_ptr<int> s = makes(5);//+        &s    0x0073f9ec shared_ptr 5 [1 strong ref] [default]    std::shared_ptr<int> *
//
//    //shared_ptr<string> p3 = make_shared<string>("hello");
//
//    //auto p6 = make_shared<int>(100);
//    //auto p7(p6);
//    //myfunc(p6);
//
//    myfunc2(p7);//此时引用计数为2
//    //auto p8 = myfunc2(p7);//此时引用计数为3 +        &p6    0x0073f9dc shared_ptr 100 [2 strong refs] [make_shared]    std::shared_ptr<int> *
//
//
//    //p8 = make_shared<int>(10);//此时p8指向新对象引用计数为1, p7和p6指向之前对象为2
//
//
//    //auto p9 = make_shared<int>(100);
//    //auto p10 = make_shared<int>(100);
//    //p9 = p10;
//
//    //int count = p9.use_count();
//    //if (p9.unique()) { //相当于use_count等于1
//    //    cout << "是否独享的" << endl;
//    //}
//    //else {
//    //    cout << "不是否独享的" << endl;
//    //}
//
//    //p9.reset();//不带参数,p9重置,p10则引用计数减1
//    //if (p9 == nullptr) {
//    //    cout << "p9 为空" << endl;
//    //}
//    //if (p10 == nullptr) {
//    //    cout << "p10 为空" << endl;
//    //}
//    //else {
//    //    cout << "p10 use_count:" << p10.use_count() << endl;
//    //}
//
//    //shared_ptr<int> pi1(new int(100));
//    //pi1.reset(new int(20));//pi先释放之前内存,指向新内存
//
//    //shared_ptr<int> pi2(new int(100));
//    //auto pi3(pi2);//pi2和pi3引用计数都是2
//    //pi2.reset(new int(20));//pi先释放之前内存,指向新内存
//
//    //int *p = pi2.get();
//
//    自定义删除器
//    方法1
//    shared_ptr<int> p(new int(100), myDelete);
//    shared_ptr<int> p2(p);
//    p2.reset();
//    p.reset();
//
//    方法2 lambda
//    //shared_ptr<int> ps(new int(100), [](int *pa) {
//    //    cout << "delete pa" << endl;
//    //    delete pa;
//    //});
//
//    有些情况默认删除器处理不了,比如用shared_ptr管理动态数组,需要自己提供删除器
//    //shared_ptr<int> p(new int[10], [](int *p) {
//    //    delete[]p;
//    //});
//
//    方法3 用default_delete删除器,是标准库的模板类
//    //shared_ptr<A> pA(new A[10], std::default_delete<A[]>());
//
//    方法4 只有c++17才支持
//    //shared_ptr<A[]> pA1(new A[10]);
//    //shared_ptr<int[]> pA2(new int[10]);
//    //pA2[0] = 1;
//    //pA2[1] = 2;
//    //cout << "pA2[0]=" << pA2[0] << endl;
//    //cout << "pA2[1]=" << pA2[1] << endl;
//
//    函数模板定义数组删除器
//    //shared_ptr<A> p11 = my_shared_array<A>(10);
//
//    //指定删除器的额外说明
//    //就算是两个shared_ptr指定了不同的删除器,只是他们所指定的对象类型相同,那么者两个share_ptr属于同一类型
//    auto lambda1 = [](int *p) {
//        cout << "delete p1" << endl;
//        delete p;
//    };
//    auto lambda2 = [](int *p) {
//        cout << "delete p2" << endl;
//        delete p;
//    };
//    shared_ptr<int> p1(new int(100), lambda1);
//    shared_ptr<int> p2(new int(100), lambda2);
//    p2 = p1;//p2释放,调用lambda2,然后指向p1指向的对象,p1指向对象引用计数为2
//    p2.reset();
//
//    cout << "end" << endl;
//    return 0;
//} 

//int main()
//{
//    //weak_ptr也是类模板,这个智能指数指向一个由shared_ptr管理的对象,但weak_ptr不控制生命周期
//    //weak_ptr的构造和析构不会改变shared_ptr的引用计数
//    //当shared_ptr需要释放所指定对象的时候照常释放,不管是否有weak_ptr指向该对象。
//    //作用:监视shared_ptr(强引用)的生命周期,是shared_ptr的扩充,不是一种独立的智能指针,不能用来
//    //      操作所指向的资源,是shared_ptr的助手,用来监视shared_ptr所指向的对象是否存在
//
//    auto pi = make_shared<int>(100);
//    weak_ptr<int> piw(pi);
//    weak_ptr<int> piw2 = piw;
//
//    //pi.reset();
//    //shared_ptr<int> piw3 = piw.lock();//lock返回的是shared_ptr对象
//    //if (piw3 != nullptr) {
//    //    //所指向的对象存在
//    //    *piw3 = 12;
//    //}
//    //else {
//    //    //所指向的对象不存在
//    //    cout << "所指向的对象不存在" << endl;
//    //}
//
//    //weak_ptr的use_count()是获取该对象的shared_ptr的引用计数大小
//    cout << "pi的shared_ptr的引用计数大小:" << piw2.use_count() << endl;
//
//    //expired 检测对象是否释放,use_count=0
//    pi.reset();
//    if (piw2.expired()) {
//        cout << "所指向的对象已经过期" << endl;
//    }
//
//    //reset() 将弱引用设置为空,不影响该对象的shared_ptr的强引用计数,但指向该对象的弱引用计数会减1
//    //piw.reset();
//
//    //尺寸问题
//    //weak_ptr和shared_ptr尺寸一样的,是裸指针的2倍
//    weak_ptr<int> pw1;
//    int *pt;
//    int len1 = sizeof(pt);//4字节
//    int len2 = sizeof(pw1);//8字节
//
//    cout << "end" << endl;
//    return 0;
//}

class CT : enable_shared_from_this<CT>
{
public:
    shared_ptr<CT> getself()
    {
        //return shared_ptr<CT>(this);//这是类似于用this裸指针初始化
        return shared_from_this();
    }
};

//int main()
//{
//    //1.
//    //不能把get返回的指针,再绑定到智能指针上
//    //不要将get得到的指针来初始化另外一个智能指针或者给另外一个智能指针赋值
//    shared_ptr<int> myp(new int(100));
//    int *p = myp.get();//这个p不能随意释放,否则智能指针就不能正常管理该指针了
//    //shared_ptr<int> myp2(p);//不能这样写,否则会出现异常
//
//    //2.
//    //不要把类对象指针(this)作为shared_ptr返回,改用enable_shared_from_this
//    //在调用shared_from_this方法时,实际上是调用了这个weak_ptr的lock()方法,
//    //lock方法会让shared_ptr计时器加1,同时返回shared_ptr
//    //shared_ptr<CT> ptrc1(new CT);
//    //shared_ptr<CT> ptrc2 = ptrc1->getself();
//
//    //3.
//    //移动语义
//    shared_ptr<int> p1(new int(100));
//    shared_ptr<int> p2(std::move(p1));//移动比复制快,复制引用计数会加1,移动不会
//    shared_ptr<int> p3;
//    p3 = std::move(p2);
//
//    //4.
//    //不要用new shared_ptr<T>,memcpy()
//
//    //优先使用make_shared()
//    shared_ptr<string> ps1(new string("I love china")); //分配2次内存
//    auto ps2 = make_shared<string>("I love china");//此方式只分配1次内存
//
//    cout << "end" << endl;
//    return 0;
//}

//auto my_func1() {
//    return unique_ptr<string>(new string("I love china"));//这是右值引用,临时对象都是右值引用
//}
//
//int main()
//{
//    1.1
//    unique_ptr不支持的操作(独占式)
//    //unique_ptr<string> ps1(new string("I love china"));
//    //unique_ptr<string> ps2(ps1);//该智能指针不支持拷贝动作
//    //unique_ptr<string> ps3 = ps1;//该智能指针不支持拷贝动作
//    //unique_ptr<string> ps4;
//    //ps4 = ps1;//不支持赋值操作
//
//    //1.2
//    make_unique函数
//    c++11中没有,c++14才有,make_unique不支持指定的删除器,如果不用删除器,建议优先选择使用,因为有更高的信息
//    //unique_ptr<int> p1 = make_unique<int>(100);
//    //auto p2 = make_unique<int>(200);
//    //unique_ptr<int> pi2(new int(105));//前边不能简写为auto
//
//    //2.
//    std::move
//    //unique_ptr<string> psa1(new string("I love china"));
//    //unique_ptr<string> psa2 = std::move(psa1);//移动后psa1为空,psa2指向原来对象
//
//    //3.
//    release():放弃对指针的控制权(切断了智能指针和其所指向的对象的关系)
//    返回的是裸指针,将该智能指针置空。返回的这个裸指针我们可以用手动delete来释放,
//    也可以用来初始化另外一个智能指针,或者给另外智能指针赋值
//    //unique_ptr<string> ps1(new string("I love china"));
//    //unique_ptr<string> ps2(ps1.release());
//    //if (ps1 == nullptr) {
//    //    cout << "ps1 为空" << endl;
//    //}
//
//    //ps2.release();//会导致内存泄漏
//    string *str = ps2.release();
//    delete str;//这样不会内存泄漏
//
//    4.
//    4.1 reset()不带参数情况:释放智能指针所指向的对象,并将智能指针置空
//    //unique_ptr<string> ps(new string("I love china"));
//    //ps.reset();
//    //if (ps == nullptr) {
//    //    cout << "ps 为空" << endl;
//    //}
//    4.2 reset()带参数,释放智能指针所指向之前的对象,并指向新对象
//    //unique_ptr<string> ps1(new string("I love china1"));//0578
//    //unique_ptr<string> ps2(new string("I love china2"));//1c10
//    //ps1.reset(ps2.release());//reset释放ps1指向的对象内存,让ps1指向ps2所指向的内存,同时ps2被置空
//
//    5.
//    = nullptr: 释放智能指针所指向的对象,并将智能指针置空
//    //unique_ptr<string> ps1(new string("I love china1"));
//    //ps1 = nullptr;//释放ps1所指向的对象,并将ps1置空
//
//    6.
//    get():返回智能指针的裸指针
//    //unique_ptr<string> ps1(new string("I love china1"));
//    //string *str = ps1.get();
//    //*str = "This is test";
//    delete str;//千万不要这么做,否则会出现不可预料问题
//
//
//    //7.
//    *解引用:获取该智能指针指向的对象,可以直接操作
//    //unique_ptr<string> ps1(new string("I love china1"));
//    //*ps1 = "This is test";
//    //unique_ptr<int> ps2(new int(10));
//    //*ps2 = 100;
//
//    //8.
//    //swap():交换两个智能指针所指向的对象
//    //unique_ptr<string> ps1(new string("I love china1"));
//    //unique_ptr<string> ps2(new string("I love china2"));
//    //std::swap(ps1, ps2);
//    //ps1.swap(ps2);
//
//    //9.
//    判断指针
//    //unique_ptr<string> ps(new string("I love china1"));
//    //if (ps) {
//    //    cout << "ps 不为空" << endl;
//    //}
//    //else {
//    //    cout << "ps 为空" << endl;
//    //}
//    //ps.reset();
//    //if (ps) {
//    //    cout << "ps 不为空" << endl;
//    //}
//    //else {
//    //    cout << "ps 为空" << endl;
//    //}
//
//    //10.
//    转换成shared_ptr类型:如果unique_ptr为右值,就可以将它赋值给shared_ptr 
//    因为shared_ptr包含一个显示构造函数,可以用于将右值unique_ptr转换为shared_ptr,shared_ptr将接管原来unique_ptr的对象
//    //unique_ptr<string> ps1(new string("I love china1"));
//    //shared_ptr<string> pss1 = std::move(ps1);//左值转右值,执行后ps1为空
//
//    //shared_ptr<string> pss2 = my_func1();
//
//    cout << "end" << endl;
//    return 0;
//}

void my_delete(string *p) {
    delete p;
    p = nullptr;
}

int main()
{
    //1.
    //指定删除器,delete:默认删除器
    //a)指定删除器
    //格式:unique_ptr<指定的对象类型,删除器的类型> 智能指针变量名
    //删除器,可调用对象,比如函数,类重载
    //shared_ptr删除器用法,shared_ptr<int> p(new int(), mydelete);
    //unique_ptr删除器复杂一些,多了一步,先要在类型模板参数中传递进来类型名,然后在参数中再给具体的删除函数
    写法1
    //typedef void(*fp)(string *);
    //unique_ptr<string, fp> ps(new string("I love china"), my_delete);
    写法2
    //using fp2 = void(*)(string *);
    //unique_ptr<string, fp2> ps1(new string("I love china"), my_delete);
    写法3
    //typedef decltype(my_delete)* fp3;//多一个*,因为decltype返回的是一个函数类型void(string *),加*表示函数指针类型,变成了void *(string *), 是函数指针
    //unique_ptr<string, fp3> ps4(new string("I love china"), my_delete);
    写法4
    //unique_ptr<string, decltype(my_delete)*> ps4(new string("I love china"), my_delete);
    写法5 lambda表达式,lambda表达式理解成带有operator()类类型对象
    所以decltype(myDel)=class{...}
    //auto myDel = [](string *pdel) {//把lambda表达式理解成一个class
    //    delete pdel;
    //    pdel = nullptr;
    //};
    //unique_ptr<string, decltype(myDel)> ps5(new string("I love china"), myDel);

    //2
    尺寸
    //string *p;
    //int len1 = sizeof(p);//4字节
    //unique_ptr<string> ps(new string("I love china"));
    //int len2 = sizeof(ps);//4字节
    //如果自己的删除器,则unique_ptr尺寸有可能增加,有可能不增加
    //2.1如果是lambda表达式删除器,尺寸不变
    //int len3 = sizeof(ps5);//4字节
    //2.2定义的是函数删除器,尺寸发生变化,变成8,效率可定没那么高
    //int len4 = sizeof(ps4);//8字节

    //3
    //智能指针设计思想:将基本类型指针封装为类对象指针(这个类肯定是个模板,以适应不同基本类型的需求),
    //并在析构函数里编写delete语句删除指针指向的内存空间。

    //4
    //auto_ptr弃用的原因:
    //4.1 auto_ptr不能在容器中保存,也不能从函数中返回auto_ptr
    //4.2 
    //auto_ptr<string> ps(new string("I love china"));
    //auto_ptr<string> ps2 = ps;//ps2指向了ps,但ps变成空,假如再用ps则会促出现奔溃
    //4.3 auto_ptr和unique_ptr都是独占式的,但unique_ptr这种情况在赋值的时候会出现编译时错误
    //unique_ptr<string> ps1(new string("I love china"));
    //unique_ptr<string> ps3 = ps1;//该智能指针不支持拷贝动作

    cout << "end" << endl;
    return 0;
}

 

おすすめ

転載: blog.csdn.net/hyl999/article/details/107721663