C++ åèæå
- C++11
- C++14
- C++17
- C++20
- C++ ç¼è¯å¨æ¯ææ åµè¡¨
- ç¬ç«ä¸å®¿ä¸»å®ç°
- C++ è¯è¨
- å鿍¡æ¿(C++14 èµ·)
- æ´æ°åé¢é
- èååå§å
- æ¯è¾è¿ç®ç¬¦
- é»è®¤æ¯è¾(C++20 èµ·)
- 转ä¹åºå
- for 循ç¯
- while 循ç¯
- ç¨æ·å®ä¹è½¬æ¢
- SFINAE
- 䏻彿°
- ASCII ç 表
- æ è¯ç¬¦
- ç±»å
- å 忍¡å
- 对象
- åºæ¬æ¦å¿µ
- 表达å¼
- 声æ
- åå§å
- 彿°
- è¯å¥
- ç±»
- è¿ç®ç¬¦éè½½
- 模æ¿
- å¼å¸¸
- äºå¡æ§å å
- å ä½ç¬¦ç±»å说æç¬¦ (C++11 èµ·)
- decltype 说æç¬¦
- 彿°å£°æ
- final 说æç¬¦ (C++11 èµ·)
- override 说æç¬¦(C++11 èµ·)
- å¼ç¨å£°æ
- ç§»å¨æé 彿°
- ç§»å¨èµå¼è¿ç®ç¬¦
- æä¸¾å£°æ
- constexpr 说æç¬¦(C++11 èµ·)
- å表åå§å (C++11 èµ·)
- æé 彿°ä¸æååå§åå¨å表
- using 声æ
- nullptrï¼æéåé¢é
- åºç¡ç±»å
- ç±»åå«åï¼å«å模ç (C++11 èµ·)
- å½¢åå
- èåä½å£°æ
- å符串åé¢é
- ç¨æ·å®ä¹åé¢é (C++11 èµ·)
- 屿§è¯´æç¬¦åºå(C++11 èµ·)
- Lambda è¡¨è¾¾å¼ (C++11 èµ·)
- noexcept 说æç¬¦ (C++11 èµ·)
- noexcept è¿ç®ç¬¦ (C++11 èµ·)
- alignof è¿ç®ç¬¦(C++11 èµ·)
- alignas 说æç¬¦ (C++11 èµ·)
- åå¨ç±»è¯´æç¬¦
- åºäºèå´ç for å¾ªç¯ (C++11 èµ·)
- static_assert 声æ
- éå¼è½¬æ¢
- 代ç¨è¿ç®ç¬¦è¡¨ç¤º
- èªå¢/èªåè¿ç®ç¬¦
- æå 表达å¼(C++17 èµ·)
- 类模æ¿å®åæ¨å¯¼(C++17 èµ·)
- 模æ¿å½¢å䏿¨¡æ¿å®å
- if è¯å¥
- inline 说æç¬¦
- ç»æåç»å®å£°æ (C++17 èµ·)
- switch è¯å¥
- å符åé¢é
- å½å空é´
- æ±å¼é¡ºåº
- å¤å¶æ¶é¤
- consteval 说æç¬¦ (C++20 èµ·)
- constinit 说æç¬¦ (C++20 èµ·)
- åç¨ (C++20)
- 模å (C++20 èµ·)
- 约æä¸æ¦å¿µ (C++20 èµ·)
- new 表达å¼
- do-while 循ç¯
- continue è¯å¥
- break è¯å¥
- goto è¯å¥
- return è¯å¥
- 卿å¼å¸¸è¯´æ
- throw 表达å¼
- try å
- å½å空é´å«å
- 类声æ
- cvï¼const ä¸ volatileï¼ç±»åéå®ç¬¦
- é»è®¤åå§å
- å¼åå§å(C++03 èµ·)
- é¶åå§å
- å¤å¶åå§å
- ç´æ¥åå§å
- 常éåå§å
- å¼ç¨åå§å
- å¼ç±»å«
- C++ è¿ç®ç¬¦ä¼å 级
- å¸å°åé¢é
- æµ®ç¹åé¢é
- typedef 说æç¬¦
- æ¾å¼ç±»å转æ¢
- static_cast 转æ¢
- dynamic_cast 转æ¢
- const_cast 转æ¢
- reinterpret_cast 转æ¢
- delete 表达å¼
- æé 彿°ä¸æååå§åå¨å表
- this æé
- 访é®è¯´æç¬¦
- åå 声æ
- virtual 彿°è¯´æç¬¦
- explicit 说æç¬¦
- éææå
- é»è®¤æé 彿°
- å¤å¶æé 彿°
- å¤å¶èµå¼è¿ç®ç¬¦
- ææå½æ°
- 类模æ¿
- 彿°æ¨¡æ¿
- æ¾å¼ï¼å ¨ï¼æ¨¡æ¿ç¹å
- æ±ç¼å£°æ
- C++ çåå²
- ä½ç¨å
- çåæ
- å®ä¹ä¸åä¸å®ä¹è§åï¼ODRï¼
- å忥æ¾
- æéå®çå忥æ¾
- æ éå®çå忥æ¾
- å¦åè§å
- æªå®ä¹è¡ä¸º
- ç¿»è¯é¶æ®µ
- 常é表达å¼
- èµå¼è¿ç®ç¬¦
- ç®æ¯è¿ç®ç¬¦
- é»è¾è¿ç®ç¬¦
- æå访é®è¿ç®ç¬¦
- å ¶ä»è¿ç®ç¬¦
- sizeof è¿ç®ç¬¦
- typeid è¿ç®ç¬¦
- æé声æ
- æ°ç»å£°æ
- è¯è¨é¾æ¥
- 详述类å说æç¬¦
- é»è®¤å®å
- åé¿å®å
- å®åä¾èµæ¥æ¾
- éè½½å³è®®
- éè½½å½æ°çå°å
- æ³¨å ¥ç±»å
- ééææ°æ®æå
- ééææå彿°
- åµå¥ç±»
- æ´¾çç±»
- 空åºç±»ä¼å
- æ½è±¡ç±»
- ä½å
- è½¬æ¢æé 彿°
- æå模æ¿
- 模æ¿å®åæ¨å¯¼
- é¨å模æ¿ç¹å
- sizeof... è¿ç®ç¬¦
- å¾ å³å
- 彿° try å
- æ©å å½åç©ºé´ std
- åæ¯ç¼©å
- RAII
- ä¸/äº/é¶ä¹æ³å
- PImpl
- é¶å¼éåå
- ç±»å
- éå¼è½¬æ¢
- 注é
- C++ å ³é®è¯
- é¢å¤çå¨
- C++ æ ååºå¤´æä»¶
- å ·åè¦æ±
- åè½ç¹æ§æµè¯ (C++20)
- å·¥å ·åº
- ç±»åæ¯æï¼åºæ¬ç±»åãRTTIãç±»åç¹æ§ï¼
- æ¦å¿µåº (C++20)
- é误å¤ç
- 卿å å管ç
- æ¥æåæ¶é´å·¥å ·
- å符串åº
- 容å¨åº
- è¿ä»£å¨åº
- èå´åº (C++20)
- ç®æ³åº
- æ°å¼åº
- è¾å ¥/è¾åºåº
- æä»¶ç³»ç»åº
- æ¬å°ååº
- æ£å表达å¼åº
- ååæä½åº
- çº¿ç¨æ¯æåº
- å®éªæ§ C++ ç¹æ§
- æç¨çèµæº
- ç´¢å¼
- std 符å·ç´¢å¼
- åç¨æ¯æ (C++20)
- C++ å ³é®è¯
ä½ç½®ï¼é¦é¡µ > C++ åèæå >C++ è¯è¨ > PImpl
PImpl
âæåå®ç°çæéâæâpImplâæ¯ä¸ç§ C++ ç¼ç¨æå·§[1]ï¼å®å°ç±»çå®ç°ç»èä»å¯¹è±¡è¡¨ç¤ºä¸ç§»é¤ï¼æ¾å°ä¸ä¸ªå离çç±»ä¸ï¼å¹¶ä»¥ä¸ä¸ªä¸éæçæéè¿è¡è®¿é®ï¼
// widget.hï¼æ¥å£ï¼ class widget { // å ¬å¼æå private: struct impl; // å®ç°ç±»çå置声æ // ä¸ç§å®ç°ç¤ºä¾ï¼è§ä¸æä¸çå ¶ä»è®¾è®¡é项åæè¡¡ std::experimental::propagate_const< // 转å const çæéå è£ å¨ std::unique_ptr< // å¯ä¸æææçä¸éææé impl>> pImpl; // æåå置声æçå®ç°ç±» };  // widget.cppï¼å®ç°ï¼ struct widget::impl { // å®ç°ç»è };
æ¤æå·§ç¨äºæé æ¥æç¨³å® ABI ç C++ åºæ¥å£ï¼ååå°ç¼è¯æ¶ä¾èµã
è§£é
å 为类çç§ææ°æ®æååä¸å ¶å¯¹è±¡è¡¨ç¤ºï¼å½±å大å°åå¸å±ï¼ä¹å 为类çç§ææå彿°åä¸éè½½å³è®®ï¼è¿åçäºæåè®¿é®æ£æ¥ä¹åï¼ï¼æ 对å®ç°ç»èç任使´æ¹é½è¦æ±è¯¥ç±»çææç¨æ·éç¼è¯ã
pImpl æç ´äºè¿ç§ç¼è¯ä¾èµï¼å®ç°çæ¹å¨ä¸ä¼å¯¼è´éç¼è¯ãç»ææ¯ï¼è¥æä¸ªåºå¨å ¶ ABI ä¸ä½¿ç¨ pImplï¼åè¿ä¸ªåºçæ°çæ¬å¯ä»¥æ´æ¹å®ç°ï¼å¹¶ä¸ä¸æ§çæ¬ä¿æ ABI å ¼å®¹ã
å¾å¤±æè¡¡
pImpl ææ³çæ¿ä»£æ¹æ¡æ¯
- å èå®ç°ï¼ç§ææååå ¬å¼æåæ¯åä¸ç±»çæå
- 纯èç±»ï¼OOP å·¥åï¼ï¼ç¨æ·è·å¾å°æä¸ªè½»é级æçº¯èçåºç±»çå¯ä¸æéï¼å®ç°ç»èåå¤äºè¦çå ¶èæå彿°çæ´¾çç±»ä¸ã
ç¼è¯é²ç«å¢
ç®åæ åµä¸ï¼pImpl å工忹æ³é½ä¼æç ´å®ç°åç±»æ¥å£çç¨æ·ä¹é´çç¼è¯æ¶ä¾èµã工忹æ³å建对è表ç䏿¬¡éèä¾èµï¼æ è对è彿°è¿è¡éæåºãæ·»å æç§»é¤é½ä¼æç ´ ABIãpImpl æ¹æ³å没æéèçä¾èµï¼ç¶èè¥å®ç°ç±»æ¯ç±»æ¨¡æ¿ç¹åï¼åä¼ä¸§å¤±ç¼è¯é²ç«å¢çä¼å¿ï¼æ¥å£çç¨æ·å¿ é¡»è§æµå°æ´ä¸ªæ¨¡æ¿å®ä¹ï¼ä»¥å®ä¾åæ£ç¡®çç¹åãè¿ç§æ åµä¸çä¸ç§å¸¸è§çè®¾è®¡æ¹æ¡æ¯ï¼ä»¥é¿å åæ°åçæ¹å¼å¯¹å®ç°è¿è¡éæï¼è¿æ¯ãC++ æ ¸å¿æåãç T.61 å¿è¿ååæ°åæå å T.84 使ç¨éæ¨¡æ¿æ ¸å¿å®ç°ä»¥æä¾ ABI 稳å®çæ¥å£ çå¦ä¸ç§ä½¿ç¨æ åµã
䏾便¥è¯´ï¼ä»¥ä¸ç类模æ¿å¨å ¶ç§ææåæ push_back 彿°ä½å å¹¶æªä½¿ç¨ç±»å T
template<class T> class ptr_vector { void **beg, **end, **cap; public: void push_back(T* p) { if (end == cap) reallocate(end - beg + 1); *end++ = p; } };
å æ¤ï¼è½æåæ ·æç§ææåä¼ éç»å®ç°ï¼èä¸ push_back å¯ä»¥è½¬åå°åæ ·æªå¨æ¥å£ä½¿ç¨ T çå®ç°ï¼
// 头æä»¶ï¼ptr_vector.hï¼ class ptr_vector_base { struct impl; // ä¸ä¾èµ T std::unique_ptr<impl> pImpl; protected: void push_back_fwd(void*); ... // è§ç¹æ®æå彿°çå®ç°é¨å }; template<class T> class ptr_vector : private ptr_vector_base { public: void push_back(T* p) { push_back_fwd(p); } };  // æºæä»¶ï¼ptr_vector.cppï¼ struct ptr_vector_base::impl { void **beg, **end, **cap; void push_back(void* p) { if (end == cap) reallocate(end - beg + 1); *end++ = p; } void reallocate(size_t sz) { ... } }; void ptr_vector_base::push_back_fwd(void* p) { pImpl->push_back(p); } ptr_vector_base::ptr_vector_base() : pImpl(std::make_unique<impl>()) {}
è¿è¡æ¶å¼é
- 访é®å¼éï¼pImpl ä¸ï¼æ¯æ¬¡å¯¹ç§ææå彿°çè°ç¨é½éè¿ä¸ä¸ªæéé´æ¥è¿è¡ãç§ææåå¯¹å ¬å¼æåçæ¯æ¬¡è®¿é®ä¹é½éè¿å¦ä¸ä¸ªæéé´æ¥è¿è¡ã两个访é®é½è·¨ç¿»è¯åå è¾¹çï¼ä»èåªè½è¢«è¿æ¥æ¶ä¼åä¼åæã注æ OO å·¥åå¯¹å ¬å¼æ°æ®åå®ç°ç»èç访é®é½è¦æ±è·¨ç¿»è¯åå é´æ¥è¿è¡ï¼èä¸ç±äºèæ´¾åèç»äºè¿æ¥æ¶ä¼å卿´å°çæºä¼ã
- 空é´å¼éï¼pImpl æ·»å ä¸ä¸ªæéå°å ¬å¼ç»åï¼å¹¶ä¸è¥æä»»ä½ç§ææåéè¦è®¿é®å ¬å¼æåï¼åè¦ä¹æ·»å å¦ä¸ä¸ªæéå°å®ç°ç»åï¼è¦ä¹æ¯æ¬¡è°ç¨è¦æ±å®çç§ææåæ¶ä½ä¸ºåæ°ä¼ éãè¥æ¯ææç¶æèªå®ä¹åé å¨ï¼åå¿ é¡»ä¸ååå¨åé å¨å®ä¾ã
- çåæç®¡çå¼éï¼pImplï¼è¿æ OO å·¥åï¼å°å®ç°å¯¹è±¡æ¾å¨å ä¸ï¼è¿å¨æé ä¸éæ¯æ¶å¼ºå äºæ¾èçè¿è¡æ¶å¼éãè¿å¯ä»¥é¨åå°ç±èªå®ä¹åé å¨æå¼¥è¡¥ï¼å 为 pImplï¼ä½é OO å·¥åï¼ç大å°å¨ç¼è¯æ¶æ¯å·²ç¥çã
å¦ä¸æ¹é¢ï¼pImpl ç±»æ¯å¯¹ç§»å¨å好çï¼æå¤§åçç±»éæä¸ºå¯ç§»å¨ pImplï¼å¯ä»¥æåå¯¹ä¿æè¿äºå¯¹è±¡ç容å¨è¿è¡æä½çç®æ³æ§è½ï¼å³ä¾¿å¯ç§»å¨ pImpl ä¹å ·æé¢å¤çè¿è¡æ¶å¼éï¼ä»»ä½å¨è¢«ç§»å¨å¯¹è±¡ä¸å®¹è®¸ä½¿ç¨å¹¶éè¦è®¿é®ç§æå®ç°çå ¬å¼æå彿°å¿ é¡»è¿è¡ç©ºæéæ£æ¥ã
| æ¬èæªå®æ åå ï¼å¾®åºåæµè¯ï¼) |
ç»´æ¤å¼é
pImpl ç使ç¨è¦æ±ä¸ç¨çç¿»è¯åå ï¼åªæå¤´æä»¶çåºæ æ³ä½¿ç¨ pImplï¼ï¼å¼å ¥ä¸ä¸ªé¢å¤ç±»ï¼ä¸ç»è½¬å彿°ï¼ä¸å½ä½¿ç¨åé 卿¶ï¼ä¼æ´é²å ¬å¼æ¥å£æä½¿ç¨çåé å¨çç»èã
å 为èæåæ¯ pImpl çæ¥å£ç»åçä¸é¨åï¼æ 模æ pImpl æå³çåç¬æ¨¡ææ¥å£ç»åã坿µè¯ç pImpl å ¸åå°è¢«è®¾è®¡ä¸ºå 许éè¿å¯ç¨æ¥å£è¾¾æå®æ´çæµè¯è¦çã
å®ç°
ç±äºæ¥å£ç±»åç对象æ§å¶å®ç°ç±»å对象ççåæï¼æåå®ç°çæééå¸¸æ¯ std::unique_ptrã
å 为 std::unique_ptr è¦æ±è¢«æåç±»åå¨ä»»ä½å®ä¾åå é¤å¨çè¯å¢ä¸åä¸ºå®æ´ç±»åï¼æ ç¹æ®æå彿°å¿ é¡»ä¸ºç¨æ·å£°æï¼ä¸å¨å®ç°ç±»ä¸ºå®æ´çå®ç°æä»¶ä¸ç±»å¤å®ä¹ã
å ä¸ºå½ const æåéè¿é const æåæéè°ç¨å½æ°æ¶ä¼è°ç¨å®ç°å½æ°çé const éè½½ï¼æ 该æéå¿ é¡»å è£ äº std::experimental::propagate_const æçä»·ç©ä¸ã
å°ææç§ææ°æ®æååææç§æéèæå彿°ç½®äºå®ç°ç±»ä¸ãå°ææå ¬å¼ãåä¿æ¤åèæåçäºæ¥å£ç±»ä¸ï¼å¯¹æ¿ä»£æ¹æ¡çè®¨è®ºè§ GOTW #100ï¼ã
è¥ä»»ä½ç§ææåéè¦è®¿é®å ¬å¼æåä¿æ¤æåï¼åå¯ä»¥å°æåæ¥å£çå¼ç¨ææéä½ä¸ºåæ°ä¼ éç»ç§æå½æ°ãå¦å¤ï¼ä¹å¯ä»¥å°å溯å¼ç¨ä½ä¸ºå®ç°ç±»çä¸é¨åç»´æã
è¥ææä½¿ç¨éé»è®¤åé å¨ä»¥æ¯æå®ç°å¯¹è±¡çåé ï¼åå¯ä»¥å©ç¨ä»»ä½å¸¸ç¨çå ·åé 卿¨¡å¼ï¼å æ¬ç¼ºç为 std::allocator çåé 卿¨¡æ¿å½¢åï¼ä»¥åç±»å为 std::pmr::memory_resource* çæé 彿°å®åã
示ä¾
æ¼ç¤ºå¸¦æ const_propagation ç pImplï¼å¸¦æä½ä¸ºåæ°ä¼ éçåæº¯å¼ç¨ï¼ä¸å ·åé å¨ï¼å¹¶å¯ç¨ä¸å¸¦è¿è¡æ¶æ£æ¥çç§»å¨
#include <iostream> #include <memory> #include <experimental/propagate_const>  // æ¥å£ï¼widget.hï¼ class widget { class impl; std::experimental::propagate_const<std::unique_ptr<impl>> pImpl; public: void draw() const; // å ¬å¼ APIï¼å°è¢«è½¬åç»å®ç° void draw(); bool shown() const { return true; } // å ¬å¼ APIï¼å®ç°å¿ é¡»è°ç¨ä¹ widget(int); ~widget(); // å®ä¹äºå®ç°æä»¶ï¼å ¶ä¸ impl æ¯å®æ´ç±»å widget(widget&&); // å®ä¹äºå®ç°æä»¶ // 注æï¼å¨è¢«ç§»å¨ç对象ä¸è°ç¨ draw() æ¯ UB widget(const widget&) = delete; widget& operator=(widget&&); // å®ä¹äºå®ç°æä»¶ widget& operator=(const widget&) = delete; };  // å®ç°ï¼widget.cppï¼ class widget::impl { int n; // ç§ææ°æ® public: void draw(const widget& w) const { if(w.shown()) // å¯¹å ¬å¼æå彿°çæ¤è°ç¨è¦æ±å溯å¼ç¨ std::cout << "drawing a const widget " << n << '\n'; } void draw(const widget& w) { if(w.shown()) std::cout << "drawing a non-const widget " << n << '\n'; } impl(int n) : n(n) {} }; void widget::draw() const { pImpl->draw(*this); } void widget::draw() { pImpl->draw(*this); } widget::widget(int n) : pImpl{std::make_unique<impl>(n)} {} widget::widget(widget&&) = default; widget::~widget() = default; widget& widget::operator=(widget&&) = default;  // ç¨æ·ï¼main.cppï¼ int main() { widget w(7); const widget w2(8); w.draw(); w2.draw(); }
è¾åºï¼
drawing a non-const widget 7 drawing a const widget 8
注解
| æ¬èæªå®æ åå ï¼æ³¨æè¿æ¥å°å¼è¯ä¹å¤æ |