1. 程式人生 > >c++11 unique_ptr && shared_ptr

c++11 unique_ptr && shared_ptr

#include <array>
#include <cassert>
#include <chrono>
#include <fstream>
#include <iostream>
#include <memory>
#include <mutex>
#include <thread>
#include <vector>

namespace std {

template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
}  // namespace std

void contains_main()
{
    // array
    {
        std::cout << "---------------std arrary contains\n";
        std::array<int, 5> stdarray = { 1, 2, 6, 4, 20 };
        for (auto it = stdarray.begin(); it != stdarray.end(); it++) {
            std::cout << *it << "\t";
        }
        std::cout << "\n";
    }
}

struct sBase {
    sBase()
    {
        std::cout << "sBase::sBase()\n";
    }
    virtual ~sBase()
    {
        std::cout << "sBase::~sBase()\n";
    }
};

struct sDerived : public sBase {
    sDerived()
    {
        std::cout << "sDerived::sDerived()\n";
    }
    virtual ~sDerived()
    {
        std::cout << "sDerived::~sDerived()\n";
    }
};

void thr(std::shared_ptr<sBase> p)
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::shared_ptr<sBase> lp = p;
    {
        static std::mutex           io_mutex;
        std::lock_guard<std::mutex> lk(io_mutex);
        std::cout << "local pointer in a thread:\n"
                  << "lp.get() = " << lp.get() << "lp.use_conut() = " << lp.use_count() << "\n";
    }
}

struct B {
    virtual void bar()
    {
        std::cout << "B::bar()\n";
    }
    virtual ~B() = default;
};

struct D : B {
    D()
    {
        std::cout << "D:D()\n";
    }
    ~D()
    {
        std::cout << "D:~D()\n";
    }
    void bar() override
    {
        std::cout << "D:bar()\n";
    }
};

std::unique_ptr<D> pass_through(std::unique_ptr<D> p)
{
    p->bar();
    return p;
}

void close_file(std::FILE* fp)
{
    std::cout << "deleter\n";
    std::fclose(fp);
}

/**
 *  1、儘量不使用相同的原始指標來建立多個shared_ptr物件
 *
 *
 *
 *
 */

void error_shared_ptr()
{
    {
        int*                 rawPtr = new int();
        std::shared_ptr<int> ptr_1(rawPtr);
        std::shared_ptr<int> ptr_2(rawPtr);
        //當我們去清理ptr_2時,清除原始指標,那麼ptr_1就會成為nullptr
    }
    {
        int                  x = 12;
        std::shared_ptr<int> ptr(&x);
        //這裡shared_ptr關聯的記憶體是堆,當析構時執行delete刪除堆上的物件會引起程式崩潰。
        //所以建議用std::make_shared<>來建立shared_ptr指標
    }
}

void smart_ptr_main()
{
    //擁有共享物件所有權的語義的智慧指標
    // shared_ptr 多個智慧指標可以共享一個物件,物件末尾一個擁有著銷燬物件的責任,並清理與該物件的多有資源
    {
        std::cout << "---------------std shared_ptr\n";
        std::shared_ptr<sBase> p = std::make_shared<sDerived>();

        std::cout << "create a shared sDerived(as a pointer to sBase)\n"
                  << "p.get() = " << p.get() << ", p.use_count() = " << p.use_count() << "\n";

        std::thread t1(thr, p), t2(thr, p), t3(thr, p);
        p.reset();  //這裡會把計數減1 p.reset(new sDerived());也可以重新指向新指標
        std::cout << "create a shared sDerived(as a pointer to sBase)\n"
                  << "p.get() = " << p.get() << ", p.use_count() = " << p.use_count() << "\n";

        std::cout << "shared ownership between 3 threads and released\n"
                  << "ownership from main:\n"
                  << "p.get() = " << p.get() << ", p.use_count() = " << p.use_count() << "\n";

        t1.join();
        t2.join();
        t3.join();
        std::cout << "all threads completed, the last one deleted sDerived\n";
    }

    // unique_ptr 擁有獨立物件所有權的智慧指標
    {
        std::cout << "---------------std shared_ptr\n";
        {
            std::cout << "unqiue ownership semantics demo\n";
            auto p = std::make_unique<D>();
            auto q = pass_through(std::move(p));
            assert(!p);  //現在p不佔任何內容並保有空指標
            q->bar();
        }  //程式碼段在此結束,q會自動釋放掉
        {
            std::cout << "runtime polymorphism demo\n";
            std::unique_ptr<B> p = std::make_unique<D>();  // p 是佔有D的unique_ptr 作為指向基類的指標
            p->bar();                                      //虛派發

            std::vector<std::unique_ptr<B>> v;
            v.push_back(std::make_unique<D>());
            v.push_back(std::move(p));
            v.emplace_back(new D);
            for (auto& p : v) {
                p->bar();
            }
        }
        {
            std::cout << "custom deleter demo\n";
            std::ofstream("demo.txt") << 'x';
            std::unique_ptr<std::FILE, void (*)(std::FILE*)> fp(std::fopen("demo.txt", "r"), close_file);
            if (fp) {
                std::cout << ( char )std::fgetc(fp.get()) << "\n";
            }
        }  //這裡會呼叫自定義的deleter函式 close_file, 只有fopen成功

        {
            std::cout << "custom lambda-expression deleter demo\n";
            std::unique_ptr<D, std::function<void(D*)>> p(new D, [](D* ptr) {
                std::cout << "destorying from a custom deleter...\n";
                delete ptr;
            });
            p->bar();
        }  //這裡呼叫上述lambda 並銷燬D

        {
            std::cout << "array form of unique_ptr demo\n";
            std::unique_ptr<D[]> p(new D[ 3 ]);
        }
    }
}