c++11 unique_ptr && shared_ptr
阿新 • • 發佈:2019-01-04
#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 ]); } } }