zoukankan      html  css  js  c++  java
  • C++11--智能指针shared_ptr,weak_ptr,unique_ptr <memory>

    共享指针 shared_ptr

    /*********** Shared_ptr ***********/
    // 为什么要使用智能指针,直接使用裸指针经常会出现以下情况
    // 1. 当指针的生命长于所指的资源:野指针
    // 2. 当指针的生命短于所指的资源:资源泄漏
    //
    // 智能指针: 确保指针和资源的生命周期相同
    
    class Dog {
        string m_name;
      public:
          void bark() { cout << "Dog " << m_name << " rules!" << endl; }
          Dog(string name) { cout << "Dog is created: " << name << endl; m_name = name; }
          Dog() { cout << "Nameless dog created." << endl; m_name = "nameless"; }
         ~Dog() { cout << "dog is destroyed: " << m_name << endl; }
    	  //void enter(DogHouse* h) { h->setDog(shared_from_this()); }  // Dont's call shared_from_this() in constructor
    };
    
    class DogHouse {
        shared_ptr<Dog> m_pD;
    public:
        void setDog(shared_ptr<Dog> p) { m_pD = p; cout << "Dog entered house." << endl;}
    };
    
    int main ()
    {
        shared_ptr<Dog> pD(new Dog("Gunner"));
        shared_ptr<Dog> pD = make_shared<Dog>(new Dog("Gunner")); // 另一种方式,更快且更安全
        
        pD->bark();    // 重载了箭头,可以像直接操作指针一样进行操作
        cout << pD.use_count();    // 指示有多少shared_ptr指向对象
        (*pD).bark();
        
        //DogHouse h;
    //    DogHouse* ph = new DogHouse();
    //    ph->setDog(pD);
    //    delete ph;
        
        
        //auto pD2 = make_shared<Dog>( Dog("Smokey") ); // 不要对栈上的对象使用shared_ptr
    //    auto pD2 = make_shared<Dog>( *(new Dog("Smokey")) ); 
    //    pD2->bark();
    //
    //    对象一创建就应该立马放入智能指针中,避免使用裸指针
    //    Dog* p = new Dog();    // 不是一个好的使用方式,容易出错
    //    shared_ptr<int> p1(p);
    //    shared_ptr<int> p2(p);  // 出错,p会被delete两次
        
        shared_ptr<Dog> pD3;
        pD3.reset(new Dog("Tank"));
        pD3.reset();  // Dog销毁。同: pD3 = nullptr;
    //    
        //pD3.reset(pD.get());  // crashes返回raw point
        
        /********** 自定义Deleter ************/
        shared_ptr<Dog> pD4( new Dog("Victor"), 
                            [](Dog* p) {cout << "deleting a dog.
    "; delete p;}
                            );
                            // 默认的deleter是operator delete.
                            
        //shared_ptr<Dog> pDD(new Dog[3]);    // Dog[1]和Dog[2]内存泄漏
        shared_ptr<Dog> pDD(new Dog[3], [](Dog* p) {delete[] p;} );    // 所有3个Dog都会被delete
    

    弱指针 weak_ptr

    /*********** weak_ptr *********************/
    // weak_ptr对所指对象没有所有权
    // 对象何时delete,怎么delete跟我没有关系
    // 所以weak_ptr不是一直有效的,需要检查有效性。
    class Dog {
          //shared_ptr<Dog> m_pFriend;    
          weak_ptr<Dog> m_pFriend; //跟Dog* m_pFriend类似,不过提供了一层保护,没有人可以delete它。并不是永远有效的,如果weak_ptr指向的指针被delete了
      public:
          string m_name;
          void bark() { cout << "Dog " << m_name << " rules!" << endl; }
          Dog(string name) { cout << "Dog is created: " << name << endl; m_name = name; }
         ~Dog() { cout << "dog is destroyed: " << m_name << endl; }
         void makeFriend(shared_ptr<Dog> f) { m_pFriend = f; }
         void showFriend() { //cout << "My friend is: " << m_pFriend.lock()->m_name << endl;
                             if (!m_pFriend.expired()) cout << "My friend is: " << m_pFriend.lock()->m_name << endl;
                             cout << " He is owned by " << m_pFriend.use_count() << " pointers." << endl; }//lock()将其转化为shared_ptr,检查指针有效性,同时保证指针不被delete
    };
    
    int main ()    //使用共享指针的话,会资源泄漏。因为循环引用。
    {
        shared_ptr<Dog> pD(new Dog("Gunner"));
        shared_ptr<Dog> pD2(new Dog("Smokey"));
        pD->makeFriend(pD2);
        pD2->makeFriend(pD);
        
        pD->showFriend();
    }
    

    unique_ptr

    /*********** unique_ptr *********************/
    
    // Unique指针:独占对象所有权,开销比shared_ptr小
    
    class Dog {
          //Bone* pB;
          unique_ptr<Bone> pB;  // 防止内存泄漏,即使构造函数在new之后抛出异常
      public:
          string m_name;
          void bark() { cout << "Dog " << m_name << " rules!" << endl; }
          Dog() { pB = new Bone(); cout << "Nameless dog created." << endl; m_name = "nameless"; }
          Dog(string name) { cout << "Dog is created: " << name << endl; m_name = name; }
         ~Dog() { delete pB; cout << "dog is destroyed: " << m_name << endl; }
    };
    
    void test() {
        
        //Dog* pD = new Dog("Gunner");
        unique_ptr<Dog> pD(new Dog("Gunner"));
        
        pD->bark();
        /* pD做许多操作*/
        
        //Dog* p = pD.release(); //返回raw point,同时转让原对象的所有权,不会再自动delete Dog
        pD = nullptr;        // Dog("Gunner")被销毁
        //pD.reset(new Dog("Smokey"));        // Dog("Gunner")被销毁
        
        if (!pD) {
            cout << "pD is empty.
    ";
        }
        
        //delete pD;   
    }
    
    void f(unique_ptr<Dog> p) {
        p->bark();
    }
    
    unique_ptr<Dog> getDog() {
        unique_ptr<Dog> p(new Dog("Smokey"));
        return p;    // 传值返回,会自动使用move语义
    }
    
    void test2() {
        unique_ptr<Dog> pD(new Dog("Gunner"));
        unique_ptr<Dog> pD2(new Dog("Smokey"));
        pD2 = move(pD);
        // 1. Smokey is destroyed
        // 2. pD becomes empty.
        // 3. pD2 owns Gunner.
    
        pD2->bark();
    //    f(move(pD));    // "Gunner"所有权已不属于pD,在f结束后销毁
    //    if (!pD) {
    //        cout << "pD is empty.
    ";
    //    }
    //    
    //    unique_ptr<Dog> pD2 = getDog();
    //    pD2->bark();
        
        unique_ptr<Dog[]> dogs(new Dog[3]);  //参数支持数组,不需要像shared_ptr定义deleter。因为unique_ptr对数组进行了偏特化
        dogs[1].bark();
        //(*dogs).bark(); // * is not defined
    }
    
    void test3() {
        // prevent resource leak even when constructor fails
    }
    
    
    int main ()
    {
        test2();
    }
    
  • 相关阅读:
    机器学习:逻辑回归(基础理解)
    机器学习:模型泛化(L1、L2 和弹性网络)
    机器学习:模型泛化(LASSO 回归)
    机器学习:模型泛化(岭回归:Ridge Regression)
    Numpy:np.random 的使用
    ASP.NET MVC 视图层-生成链接相关(Html.ActionLink,Url.Action)
    eval实例
    <a>实现按钮的javascript+jquery编程实例
    SQL Server之XML PATH()
    分页数算法
  • 原文地址:https://www.cnblogs.com/logchen/p/10199481.html
Copyright © 2011-2022 走看看