天天看點

C++ Smart PointersSmart Pointers

Smart Pointers

  • std::unique_ptr - single ownership
  • std::shared+ptr - shared ownership
  • std::weak_ptr - temp / no ownership

Inroduced in C++ 11

頭檔案:memory

unique_ptr

std::unique_ptr<T> t1 = new T();// non-assignable
std::unique_ptr<T> t1(new T());//OK
std::unique_ptr<T> t1 = std::make_unique<T>();// preferred

auto t2 = std::make_unique<T>();// preferred
std::unique_ptr<T> t2 = t1;// non-copyable
std::unique_ptr<T> t2 = std::move(t1);// movable,transfer ownership
foo(std::move(t1));// transfer ownership
           

Example

class T {
public:
    T() {
        puts("T created !");
    }
    ~T() {
        puts("T destroied !");
    }
};

void ex1() {
    puts("Entering ex1");
    {
        puts("Entering ex1::scope1");
        auto t1 = std::make_unique<T>();
        puts("Leaving ex1::scope1");
    }
    puts("Leaving ex1");
}
//輸出
//  Entering ex1
//  Entering ex1::scope1
//  T created !
//  Leaving ex1::scope1
//  T destroied !
//  Leaving ex1

void foo(std::unique_ptr<T>) {
    puts("Entering foo");
    puts("Leaving foo");
}

void ex2() {
    puts("Entering ex2");
    auto t1 = std::make_unique<T>();
    foo(std::move(t1));
    //e1 was destroied
    puts("Leaving ex2");
}
//輸出
// Entering ex2
// T created !
// Entering foo
// Leaving foo
// T destroied !
// Leaving ex2
           

生命周期:調用結束時,自動銷毀。

shared_ptr

生命周期:use_count為0時,自動銷毀。

std::shared_ptr<T> t1(new T());//OK
std::shared_ptr<T> t1 = std::make_shared<T>();// preferred

auto t1 = std::make_shared<T>();// preferred
std::shared_ptr<T> t2 = t1;// copyable,use_count + 1
std::shared_ptr<T> t2 = std::move(t1);// movable,use_count remains
foo(std::move(t1));// use_count remains
foo(t1); //use_count + 1
           

Example

void ex3(){
    puts("Entering ex3");
    auto t1 = std::make_shared<T>();
    std::cout << t1.use_count() << std::endl;
    {
        puts("Entering ex3::scope1");
        auto t2 = t1;
        std::count << t1.use_count() << std::endl;
        auto t3 = std::move(t2);
        std::cout<< t1.use_count() << std::endl;
        puts("Leaving ex3::scope1");
    }
    std::cout << t1.use_count() << std::endl;
    puts("Leaving ex3");
}
//輸出
//  Entering ex3
//  T created!
//  1
//  Entering ex3::scope1
//  2
//  2
//  Leaving ex3::scope1
//  1
//  Leaving ex3
//  T destoryed!
           

weak_ptr Temp/No Ownership

  • 在通路之前必須轉換為 std::shared_ptr
auto t1 = std::make_shared<T>();
std::weak_ptr<T> tw = t1;   //從 shared_ptr 中構造
if(std::shared_ptr<T> t2 = tw.lock())   //轉換到 shared_ptr
    t2->DoSonmething();
           

Example

void observe(std::weak_ptr<T> tw) {
    if(std::shared_ptr<T> spt = tw.lock()) {
        std::cout << spt.use_count() << std::endl;
        std::cout << "T still alive!" << std::endl;
    }
    else {
        std::cout << "T was expired :(" << std::endl;
    }
}
void ex4() {
    puts("Entering ex4");
    std::weak_ptr<T> tw;
    {
        puts("Entering ex4::scope1");
        auto t1 = std::make_shared<T>();
        std::cout << t1.use_count() <<std::endl;
        tw = t1;    //use_count remians
        std::cout << t1.use_count() << std::endl;
        observe(tw);
        puts("Leaving ex4::scope1");
    }
    observe(tw);
    puts("Leaving ex4");
}

//輸出
//  Entering ex4
//  Entering ex4::scope1
//  T created!
//  1
//  1
//  2
//  T still alive!
//  Leaving ex4::scope1
//  T destoried!
//  T was expired:(
//  Leaving ex4
           

Conclusion

  • Time to say goobye to new / delete
    • Replace raw pointers with smart pointers
  • prefer std::unique_ptr over std::shared_ptr
  • Move std::shared_ptr whenever possible

文章筆記視訊來源

繼續閱讀