C++11--智能指针shared_ptr,weak_ptr,unique_ptr

共享指针 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.\n"; 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.\n";
    }
    
    //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.\n";
//    }
//    
//    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();
}

猜你喜欢

转载自www.cnblogs.com/logchen/p/10199481.html