C++ åèæå
- C++11
- C++14
- C++17
- C++20
- C++ ç¼è¯å¨æ¯ææ åµè¡¨
- ç¬ç«ä¸å®¿ä¸»å®ç°
- C++ è¯è¨
- C++ å ³é®è¯
- é¢å¤çå¨
- C++ æ ååºå¤´æä»¶
- å ·åè¦æ±
- åè½ç¹æ§æµè¯ (C++20)
- å·¥å ·åº
- ç±»åæ¯æï¼åºæ¬ç±»åãRTTIãç±»åç¹æ§ï¼
- æ¦å¿µåº (C++20)
- é误å¤ç
- 卿å å管ç
- std::unique_ptr
- std::scoped_allocator_adaptor
- std::auto_ptr
- std::destroy_at
- std::destroy
- std::destroy_n
- std::uninitialized_move
- std::uninitialized_value_construct
- std::owner_less
- std::shared_ptr
- std::allocate_shared, std::allocate_shared_for_overwrite
- std::make_shared, std::make_shared_for_overwrite
- std::atomic(std::shared_ptr)
- std::hash(std::shared_ptr)
- std::atomic_...<std::shared_ptr>
- std::addressof
- std::allocator_traits
- std::default_delete
- std::allocator_arg_t
- std::allocator_arg
- std::weak_ptr
- std::enable_shared_from_this
- std::bad_weak_ptr
- std::to_address
- std::assume_aligned
- std::make_obj_using_allocator
- C å å管çåº
- ä½å±å å管ç
- std::pmr::memory_resource
- std::allocator
- std::pointer_traits
- std::uses_allocator
- std::uses_allocator_construction_args
- std::uninitialized_construct_using_allocator
- std::pmr::polymorphic_allocator
- std::pmr::get_default_resource
- std::pmr::set_default_resource
- std::pmr::new_delete_resource
- std::pmr::null_memory_resource
- std::pmr::synchronized_pool_resource
- std::pmr::unsynchronized_pool_resource
- std::pmr::monotonic_buffer_resource
- std::pmr::pool_options
- std::raw_storage_iterator
- std::get_temporary_buffer
- std::return_temporary_buffer
- std::uninitialized_copy
- std::uninitialized_fill
- std::uninitialized_default_construct
- std::uninitialized_copy_n
- std::uninitialized_fill_n
- std::uninitialized_move_n
- std::uninitialized_default_construct_n
- std::uninitialized_value_construct_n
- std::construct_at
- std::align
- 注é
- æ¥æåæ¶é´å·¥å ·
- å符串åº
- 容å¨åº
- è¿ä»£å¨åº
- èå´åº (C++20)
- ç®æ³åº
- æ°å¼åº
- è¾å ¥/è¾åºåº
- æä»¶ç³»ç»åº
- æ¬å°ååº
- æ£å表达å¼åº
- ååæä½åº
- çº¿ç¨æ¯æåº
- å®éªæ§ C++ ç¹æ§
- æç¨çèµæº
- ç´¢å¼
- std 符å·ç´¢å¼
- åç¨æ¯æ (C++20)
- C++ å ³é®è¯
ä½ç½®ï¼é¦é¡µ > C++ åèæå >卿å å管ç > std::shared_ptr
std::shared_ptr
std::shared_ptr æ¯éè¿æéä¿æå¯¹è±¡å
±äº«æææçæºè½æéãå¤ä¸ª shared_ptr 对象å¯å æåä¸å¯¹è±¡ãä¸åæ
åµä¹ä¸åºç°æ¶éæ¯å¯¹è±¡å¹¶è§£åé
å
¶å
åï¼
- æåå©ä¸çå æå¯¹è±¡ç
shared_ptrè¢«éæ¯ï¼ - æåå©ä¸çå æå¯¹è±¡ç
shared_ptr被éè¿ operator= æ reset() èµå¼ä¸ºå¦ä¸æéã
ç¨ delete è¡¨è¾¾å¼æå¨æé æé´æä¾ç» shared_ptr çå®å¶å é¤å¨éæ¯å¯¹è±¡ã
shared_ptr è½å¨å卿åä¸ä¸ªå¯¹è±¡çæéæ¶å
±äº«å¦ä¸å¯¹è±¡çæææãæ¤ç¹æ§è½ç¨äºå¨å æå
¶æå±å¯¹è±¡æ¶ï¼æåæå对象ãåå¨çæé为 get() ãè§£å¼ç¨åæ¯è¾è¿ç®ç¬¦æè®¿é®ã被管çæéæ¯å¨ use_count æµè¾¾é¶æ¶ä¼ éç»å é¤å¨è
ã
shared_ptr 亦å¯ä¸å æå¯¹è±¡ï¼è¯¥æ
åµä¸ç§°å®ä¸ºç©º (empty) ï¼ç©º shared_ptr 坿¥æé空å卿éï¼è¥ä»¥å«åä½¿ç¨æé 彿°å建å®ï¼ã
shared_ptr çææç¹å满足å¯å¤å¶æé (CopyConstructible) ãå¯å¤å¶èµå¼ (CopyAssignable) åå¯å°äºæ¯è¾ (LessThanComparable) çè¦æ±å¹¶å¯æè¯å¢è½¬æ¢ä¸º bool ã
å¤ä¸ªçº¿ç¨è½å¨ shared_ptr çä¸åå®ä¾ä¸è°ç¨æææå彿°ï¼å
å«å¤å¶æé 彿°ä¸å¤å¶èµå¼ï¼èä¸éå 忥ï¼å³ä½¿è¿äºå®ä¾æ¯å¯æ¬ï¼ä¸å
±äº«åä¸å¯¹è±¡çæææãè¥å¤ä¸ªæ§è¡çº¿ç¨è®¿é®åä¸ shared_ptr èä¸åæ¥ï¼ä¸ä»»ä¸çº¿ç¨ä½¿ç¨ shared_ptr çé const æå彿°ï¼åå°åºç°æ°æ®ç«äºï¼åå彿°ç shared_ptr ç¹åè½ç¨äºé¿å
æ°æ®ç«äºã
æåç±»å
| Â | |||||
| æåç±»å | å®ä¹ | ||||
| element_type |
| ||||
| weak_type (C++17 èµ·) | std::weak_ptr<T> | ||||
æå彿°
æé æ°ç shared_ptr (å ¬å¼æå彿°) | |
å¦ææ²¡ææ´å¤ shared_ptr æåææç对象ï¼åææå¯¹è±¡ (å ¬å¼æå彿°) | |
对 shared_ptr èµå¼ (å ¬å¼æå彿°) | |
ä¿®æ¹å¨ | |
| æ¿æ¢æç®¡çç对象 (å ¬å¼æå彿°) | |
| äº¤æ¢æç®¡çç对象 (å ¬å¼æå彿°) | |
è§å¯å¨ | |
| è¿ååå¨çæé (å ¬å¼æå彿°) | |
| è§£å¼ç¨åå¨çæé (å ¬å¼æå彿°) | |
| (C++17) |
æä¾å°è¢«å卿°ç»ç另䏿 è®¿é® (å ¬å¼æå彿°) |
è¿å shared_ptr ææå¯¹è±¡çå¼ç¨è®¡æ° (å ¬å¼æå彿°) | |
| (C++20 å) |
æ£æ¥æç®¡ç对象æ¯å¦ä»
ç±å½å shared_ptr çå®ä¾ç®¡ç (å ¬å¼æå彿°) |
| æ£æ¥æ¯å¦æå
³èç管ç对象 (å ¬å¼æå彿°) | |
| æä¾åºäºæ¥æè
çå
±äº«æéæåº (å ¬å¼æå彿°) | |
éæå彿°
| å建管çä¸ä¸ªæ°å¯¹è±¡çå
±äº«æé (彿°æ¨¡æ¿) | |
| å建管çä¸ä¸ªç¨åé
å¨åé
çæ°å¯¹è±¡çå
±äº«æé (彿°æ¨¡æ¿) | |
| åºç¨ static_castãdynamic_castãconst_cast æ reinterpret_cast å°è¢«å卿é (彿°æ¨¡æ¿) | |
| è¿åæå®ç±»åä¸çå é¤å¨ï¼è¥å
¶æ¥æ (彿°æ¨¡æ¿) | |
| (C++20 ä¸ç§»é¤)(C++20 ä¸ç§»é¤)(C++20 ä¸ç§»é¤)(C++20 ä¸ç§»é¤)(C++20 ä¸ç§»é¤)(C++20) |
ä¸å¦ä¸ä¸ª shared_ptr æ nullptr è¿è¡æ¯è¾ (彿°æ¨¡æ¿) |
| å°åå¨çæéçå¼è¾åºå°è¾åºæµ (彿°æ¨¡æ¿) | |
| (C++11) |
ç¹å std::swap ç®æ³ (彿°æ¨¡æ¿) |
| ç¹åçååæä½ (彿°æ¨¡æ¿) |
è¾ å©ç±»
| (C++11) |
std::shared_ptr çæ£åæ¯æ (类模æ¿ç¹å) |
| (C++20) |
ååå
±äº«æé (类模æ¿ç¹å) |
æ¨å¯¼æå¼(C++17 èµ·)
注æ
åªè½éè¿å¤å¶æé æå¤å¶èµå¼å
¶å¼ç»å¦ä¸ shared_ptr ï¼å°å¯¹è±¡æææä¸å¦ä¸ shared_ptr å
±äº«ãç¨å¦ä¸ shared_ptr æå æçåºå±æéå建æ°ç shared_ptr å¯¼è´æªå®ä¹è¡ä¸ºã
std::shared_ptr å¯ä»¥ç¨äºä¸å®æ´ç±»å T ãç¶èï¼åæ°ä¸ºè£¸æéçæé 彿°ï¼ template<class Y> shared_ptr(Y*) ï¼å template<class Y> void reset(Y*) æå彿°åªå¯ä»¥ç¨æå宿´ç±»åçæéè°ç¨ï¼æ³¨æ std::unique_ptr å¯ä»¥ä»æåä¸å®æ´ç±»åç裸æéæé ï¼ã
å®ç°è¯´æ
å¨å ¸åçå®ç°ä¸ï¼ std::shared_ptr åªä¿æäºä¸ªæéï¼
-
get()æè¿åçæé - æåæ§å¶åçæé
æ§å¶åæ¯ä¸ä¸ªå¨æåé ç对象ï¼å ¶ä¸å å«ï¼
- æå被管ç对象çæéæè¢«ç®¡ç对象æ¬èº«
- å é¤å¨ï¼ç±»åæ¦é¤ï¼
- åé å¨ï¼ç±»åæ¦é¤ï¼
- å æè¢«ç®¡ç对象ç
shared_ptrçæ°é - æ¶å被管ç对象ç
weak_ptrçæ°é
以è°ç¨ std::make_shared æ std::allocate_shared å建 shared_ptr æ¶ï¼ä»¥å次åé
å建æ§å¶åå被管ç对象ã被管çå¯¹è±¡å¨æ§å¶åçæ°æ®æåä¸å使é ãéè¿ shared_ptr æé 彿°ä¹ä¸å建 shared_ptr æ¶ï¼è¢«ç®¡çå¯¹è±¡åæ§å¶åå¿
é¡»å离åé
ãæ¤æ
åµä¸ï¼æ§å¶åå卿å被管ç对象çæéã
shared_ptr ææçæéæ¯éè¿ get() è¿åçï¼èæ§å¶åæææçæé/å¯¹è±¡åæ¯æç»å¼ç¨è®¡æ°å½é¶æ¶ä¼è¢«å é¤çé£ä¸ªã两è
å¹¶ä¸ä¸å®ç¸çã
shared_ptr çææå½æ°ä¼å°æ§å¶åä¸ç shared_ptr 计æ°å¨åä¸ï¼å¦æåè³é¶ï¼æ§å¶åå°±ä¼è°ç¨è¢«ç®¡çå¯¹è±¡çææå½æ°ã使§å¶åæ¬èº«ç´å° std::weak_ptr 计æ°å¨åæ ·å½é¶æ¶æä¼éæ¾ã
æ¢åå®ç°ä¸ï¼è¥æå ±äº«æéæåå䏿§å¶åï¼åèªå¢å¼±æéè®¡æ° ([1], [2]) ã
为满足线ç¨å®å ¨è¦æ±ï¼å¼ç¨è®¡æ°å¨å ¸åå°ç¨çä»·äºç¨ std::memory_order_relaxed ç std::atomic::fetch_add èªå¢ï¼èªåè¦æ±æ´å¼ºç顺åºï¼ä»¥å®å ¨éæ¯æ§å¶åï¼ã
示ä¾
#include <iostream> #include <memory> #include <thread> #include <chrono> #include <mutex>  struct Base { Base() { std::cout << " Base::Base()\n"; } // 注æï¼æ¤å¤éèææå½æ° OK ~Base() { std::cout << " Base::~Base()\n"; } };  struct Derived: public Base { Derived() { std::cout << " Derived::Derived()\n"; } ~Derived() { std::cout << " Derived::~Derived()\n"; } };  void thr(std::shared_ptr<Base> p) { std::this_thread::sleep_for(std::chrono::seconds(1)); std::shared_ptr<Base> lp = p; // 线ç¨å®å ¨ï¼è½ç¶èªå¢å ±äº«ç use_count { 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_count() = " << lp.use_count() << '\n'; } }  int main() { std::shared_ptr<Base> p = std::make_shared<Derived>();  std::cout << "Created a shared Derived (as a pointer to Base)\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(); // ä» main éæ¾æææ 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 Derived\n"; }
å¯è½çè¾åºï¼
Base::Base() Derived::Derived() Created a shared Derived (as a pointer to Base) p.get() = 0xc99028, p.use_count() = 1 Shared ownership between 3 threads and released ownership from main: p.get() = (nil), p.use_count() = 0 local pointer in a thread: lp.get() = 0xc99028, lp.use_count() = 3 local pointer in a thread: lp.get() = 0xc99028, lp.use_count() = 4 local pointer in a thread: lp.get() = 0xc99028, lp.use_count() = 2 Derived::~Derived() Base::~Base() All threads completed, the last one deleted Derived