มี std :: shared_ptr ที่ไม่ใช่อะตอมหรือไม่ แล้วทำไมไม่มีใน <memory>?


90

นี่เป็นคำถามสองส่วนเกี่ยวกับปรมาณูของstd::shared_ptr:

1. เท่าที่ฉันสามารถบอกได้std::shared_ptrคือตัวชี้อัจฉริยะเพียงตัวเดียวใน<memory>อะตอมนั้น ฉันสงสัยว่ามีเวอร์ชันที่ไม่ใช่อะตอมหรือไม่std::shared_ptr(ฉันมองไม่เห็นอะไรเลย<memory>ดังนั้นฉันจึงเปิดรับข้อเสนอแนะที่อยู่นอกเหนือจากมาตรฐานเช่นใน Boost) ฉันรู้ว่าboost::shared_ptrเป็นปรมาณู (ถ้าBOOST_SP_DISABLE_THREADSไม่ได้กำหนดไว้) แต่อาจมีทางเลือกอื่น? ฉันกำลังมองหาสิ่งที่มีความหมายเหมือนstd::shared_ptrกัน แต่ไม่มีความเป็นอะตอม

2.ฉันเข้าใจว่าทำไมstd::shared_ptrอะตอม; มันก็ดีนะ อย่างไรก็ตามมันไม่ดีสำหรับทุกสถานการณ์และในอดีต C ++ มีมนต์ตราว่า "จ่ายเฉพาะสิ่งที่คุณใช้เท่านั้น" ถ้าฉันไม่ได้ใช้เธรดหลายเธรดหรือฉันกำลังใช้เธรดหลายเธรด แต่ฉันไม่ได้แชร์ความเป็นเจ้าของพอยน์เตอร์ข้ามเธรดตัวชี้สมาร์ทอะตอมจะมากเกินไป คำถามที่สองของฉันคือเหตุผลที่ไม่ได้เป็นรุ่นที่ไม่ใช่ของอะตอมstd::shared_ptrที่ระบุไว้ใน C ++ 11 ? (สมมติว่ามีสาเหตุ ) (หากคำตอบคือ "เวอร์ชันที่ไม่ใช่อะตอมก็ไม่เคยพิจารณา" หรือ "ไม่เคยมีใครขอเวอร์ชันที่ไม่ใช่อะตอม" ก็ไม่เป็นไร!)

สำหรับคำถาม # 2 ฉันสงสัยว่ามีใครเคยเสนอรุ่นที่ไม่ใช่อะตอมของshared_ptr(ไม่ว่าจะเป็น Boost หรือคณะกรรมการมาตรฐาน) (ไม่ใช่เพื่อแทนที่รุ่นอะตอมshared_ptrแต่จะอยู่ร่วมกับมัน) และมันถูกยิงลงสำหรับ เหตุผลเฉพาะ


4
คุณกังวลเกี่ยวกับ "ค่าใช้จ่าย" เท่าใด ต้นทุนของการเพิ่มจำนวนเต็มด้วยอะตอม? นั่นเป็นค่าใช้จ่ายที่เกี่ยวข้องกับการใช้งานจริงหรือไม่? หรือคุณเพิ่งปรับให้เหมาะสมก่อนเวลาอันควร?
Nicol Bolas

9
@NicolBolas: มันเป็นความอยากรู้อยากเห็นมากกว่าสิ่งอื่นใด ฉันไม่มี (ปัจจุบัน) มีรหัส / โครงการที่ฉันต้องการใช้ตัวชี้ที่ใช้ร่วมกันที่ไม่ใช่อะตอมอย่างจริงจัง อย่างไรก็ตามฉันเคยมีโครงการ (ในอดีต) ที่ Boost shared_ptrมีการชะลอตัวอย่างมีนัยสำคัญเนื่องจากความเป็นอะตอมและการกำหนดBOOST_DISABLE_THREADSทำให้เกิดความแตกต่างอย่างเห็นได้ชัด (ฉันไม่รู้ว่าstd::shared_ptrจะมีต้นทุนเท่ากันหรือboost::shared_ptrไม่)
Cornstalks

13
@ ปิดผู้มีสิทธิเลือกตั้ง: ส่วนใดของคำถามที่ไม่สร้างสรรค์? หากไม่มีเหตุผลที่เฉพาะเจาะจงสำหรับคำถามที่สองก็ไม่เป็นไร (คำตอบง่ายๆ "มันไม่ได้พิจารณา" จะเป็นคำตอบที่ถูกต้องเพียงพอ) ฉันอยากรู้ว่ามีเหตุผล / เหตุผลที่เฉพาะเจาะจงหรือไม่ และคำถามแรกเป็นคำถามที่ถูกต้องฉันจะบอกว่า หากฉันต้องการชี้แจงคำถามหรือปรับเปลี่ยนเล็กน้อยโปรดแจ้งให้เราทราบ แต่ฉันไม่เห็นว่ามันไม่สร้างสรรค์
Cornstalks

10
@Cornstalks ดีก็อาจจะเพียงแค่ว่าคนที่ไม่ตอบสนองที่ดีในคำถามพวกเขาสามารถยกเลิกการเป็น"การเพิ่มประสิทธิภาพก่อนวัยอันควร"ไม่ว่าวิธีการที่ถูกต้องดีถูกวางหรือที่เกี่ยวข้องคำถามคือผมคิดว่า ตัวฉันเองไม่เห็นเหตุผลที่จะปิดสิ่งนี้ว่าไม่สร้างสรรค์
Christian Rau

13
(ไม่สามารถเขียนคำตอบได้ตอนนี้ปิดแล้วดังนั้นจึงแสดงความคิดเห็น) ด้วย GCC เมื่อโปรแกรมของคุณไม่ใช้เธรดหลายเธรดshared_ptrจะไม่ใช้ atomic ops สำหรับการอ้างอิง โปรดดู (2) ที่gcc.gnu.org/ml/libstdc++/2007-10/msg00180.htmlสำหรับการแก้ไขไปยัง GCC เพื่อให้สามารถใช้การใช้งานแบบไม่ใช้อะตอมได้แม้ในแอปมัลติเธรดสำหรับshared_ptrวัตถุที่ไม่ได้ใช้ร่วมกัน เธรด ฉันนั่งอยู่บนแพตช์นั้นมาหลายปีแล้ว แต่ในที่สุดฉันก็พิจารณาที่จะตกลงสำหรับ GCC 4.9
Jonathan Wakely

คำตอบ:


107

1. ฉันสงสัยว่ามี std :: shared_ptr เวอร์ชันที่ไม่ใช่อะตอมหรือไม่

ไม่ได้จัดทำโดยมาตรฐาน อาจมีไลบรารี "บุคคลที่สาม" จัดเตรียมไว้ให้ อันที่จริงก่อน C ++ 11 และก่อน Boost ดูเหมือนว่าทุกคนจะเขียนการอ้างอิงของตัวเองนับตัวชี้อัจฉริยะ (รวมถึงตัวฉันเองด้วย)

2. คำถามที่สองของฉันคือทำไม std :: shared_ptr เวอร์ชันที่ไม่ใช่อะตอมจึงไม่มีให้ใน C ++ 11?

คำถามนี้ถูกพูดถึงในการประชุม Rapperswil ในปี 2010 หัวข้อนี้ได้รับการแนะนำโดย National Body Comment # 20 โดยสวิตเซอร์แลนด์ มีข้อโต้แย้งที่ชัดเจนทั้งสองด้านของการอภิปรายรวมถึงประเด็นที่คุณระบุในคำถามของคุณ อย่างไรก็ตามในตอนท้ายของการสนทนา, การออกเสียงลงคะแนนขาดลอย ( แต่ไม่ได้เป็นเอกฉันท์) กับการเพิ่มหมู่ (ไม่ใช่อะตอม) shared_ptrรุ่น

ข้อโต้แย้งรวม:

  • โค้ดที่เขียนด้วย shared_ptr ที่ไม่ซิงโครไนซ์อาจถูกนำไปใช้ในโค้ดแบบเธรดตามท้องถนนทำให้เกิดปัญหาในการดีบักได้ยากโดยไม่มีคำเตือน

  • การมี shared_ptr แบบ "สากล" หนึ่งรายการซึ่งเป็น "ทางเดียว" ในการรับส่งข้อมูลในการนับอ้างอิงมีประโยชน์: จากข้อเสนอเดิม :

    มีประเภทอ็อบเจ็กต์เหมือนกันโดยไม่คำนึงถึงคุณสมบัติที่ใช้ช่วยอำนวยความสะดวกในการทำงานร่วมกันระหว่างไลบรารีรวมถึงไลบรารีของบุคคลที่สาม

  • ต้นทุนของอะตอมในขณะที่ไม่เป็นศูนย์นั้นไม่ได้ท่วมท้น ค่าใช้จ่ายลดลงโดยการใช้การก่อสร้างการย้ายและการมอบหมายการย้ายซึ่งไม่จำเป็นต้องใช้การดำเนินการของปรมาณู การดำเนินการดังกล่าวมักใช้ในการvector<shared_ptr<T>>ลบและแทรก

  • ไม่มีอะไรห้ามไม่ให้ผู้คนเขียนตัวชี้อัจฉริยะที่ไม่นับการอ้างอิงที่ไม่ใช่อะตอมของตนเองหากนั่นคือสิ่งที่พวกเขาต้องการทำจริงๆ

คำพูดสุดท้ายจาก LWG ใน Rapperswil ในวันนั้นคือ:

ปฏิเสธ CH 20 ไม่มีฉันทามติที่จะทำการเปลี่ยนแปลงในขณะนี้


7
ว้าวสมบูรณ์แบบขอบคุณสำหรับข้อมูล! นั่นเป็นข้อมูลที่ฉันหวังว่าจะพบ
Cornstalks

> Has the same object type regardless of features used, greatly facilitating interoperability between libraries, including third-party libraries. นั่นเป็นเหตุผลที่แปลกมาก ไลบรารีของบุคคลที่สามจะจัดเตรียมประเภทของตัวเองไว้แล้วดังนั้นทำไมจึงมีความสำคัญหากพวกเขาจัดเตรียมไว้ภายใต้รูปแบบของ std :: shared_ptr <CustomType>, std :: non_atomic_shared_ptr <CustomType> ฯลฯ คุณจะต้องปรับรหัสของคุณให้เข้ากับสิ่งที่ไลบรารีส่งคืนทุกครั้ง
Jean-Michaël Celerier

นั่นเป็นความจริงตราบเท่าที่ประเภทเฉพาะไลบรารีไป แต่แนวคิดก็คือยังมีสถานที่มากมายที่ประเภทมาตรฐานแสดงใน API ของบุคคลที่สาม ตัวอย่างเช่นห้องสมุดของฉันอาจstd::shared_ptr<std::string>อยู่ที่ไหนสักแห่ง หากห้องสมุดของคนอื่นใช้ประเภทนั้นด้วยผู้โทรสามารถส่งต่อสตริงเดียวกันให้กับเราทั้งสองคนได้โดยไม่ต้องยุ่งยากหรือเสียค่าใช้จ่ายในการแปลงระหว่างการเป็นตัวแทนที่แตกต่างกันและนั่นเป็นประโยชน์เล็กน้อยสำหรับทุกคน
Jack O'Connor

52

Howard ตอบคำถามได้ดีอยู่แล้วและ Nicol ได้ให้ประเด็นที่ดีเกี่ยวกับประโยชน์ของการมีชนิดตัวชี้ที่ใช้ร่วมกันมาตรฐานเดียวแทนที่จะเป็นชนิดที่เข้ากันไม่ได้

แม้ว่าฉันจะเห็นด้วยอย่างสมบูรณ์กับการตัดสินใจของคณะกรรมการ แต่ฉันคิดว่ามีประโยชน์บางอย่างในการใช้shared_ptrประเภทที่ไม่ตรงกัน- เหมือนในกรณีพิเศษดังนั้นฉันจึงตรวจสอบหัวข้อนี้สองสามครั้ง

ถ้าฉันไม่ได้ใช้เธรดหลายเธรดหรือฉันกำลังใช้เธรดหลายเธรด แต่ฉันไม่ได้แชร์ความเป็นเจ้าของพอยน์เตอร์ข้ามเธรดตัวชี้สมาร์ทอะตอมจะมากเกินไป

ด้วย GCC เมื่อโปรแกรมของคุณไม่ใช้หลายเธรด shared_ptr ไม่ได้ใช้ atomic ops สำหรับ refcount สิ่งนี้ทำได้โดยการอัปเดตจำนวนการอ้างอิงผ่านฟังก์ชัน wrapper ที่ตรวจจับว่าโปรแกรมเป็นแบบมัลติเธรดหรือไม่ (บน GNU / Linux ซึ่งทำได้ง่ายๆโดยการตรวจสอบว่าโปรแกรมเชื่อมโยงไปยังlibpthread.so) และส่งไปยังการดำเนินการแบบอะตอมหรือไม่ใช่อะตอมตามนั้น

ฉันรู้ว่าหลายปีที่ผ่านมาว่าเป็นเพราะของ GCC shared_ptr<T>จะดำเนินการในแง่ของ__shared_ptr<T, _LockPolicy>ชั้นฐาน__shared_ptr<T, __gnu_cxx::_S_single>ก็เป็นไปได้ที่จะใช้ชั้นฐานกับเธรดเดียวล็อคนโยบายแม้ในรหัสแบบมัลติเธรดโดยใช้อย่างชัดเจน น่าเสียดายเพราะนั่นไม่ใช่กรณีการใช้งานที่ตั้งใจไว้มันจึงไม่ทำงานได้ดีที่สุดก่อน GCC 4.9 และการดำเนินการบางอย่างยังคงใช้ฟังก์ชันของ wrapper ดังนั้นจึงส่งไปที่การปฏิบัติการปรมาณูแม้ว่าคุณจะร้องขอ_S_singleนโยบายอย่างชัดเจนก็ตาม ดูประเด็น (2) ที่http://gcc.gnu.org/ml/libstdc++/2007-10/msg00180.htmlสำหรับรายละเอียดเพิ่มเติมและการแก้ไข GCC เพื่อให้สามารถใช้งานแบบไม่ใช้อะตอมได้แม้ในแอปมัลติเธรด ฉันนั่งบนแพตช์นั้นมาหลายปี แต่ในที่สุดฉันก็ตกลงสำหรับ GCC 4.9 ซึ่งช่วยให้คุณใช้เทมเพลตนามแฝงเช่นนี้เพื่อกำหนดประเภทตัวชี้ที่ใช้ร่วมกันที่ไม่ปลอดภัยต่อเธรด แต่เร็วกว่าเล็กน้อย:

template<typename T>
  using shared_ptr_unsynchronized = std::__shared_ptr<T, __gnu_cxx::_S_single>;

ประเภทนี้จะไม่สามารถทำงานร่วมกันได้std::shared_ptr<T>และจะปลอดภัยที่จะใช้ก็ต่อเมื่อได้รับการรับรองว่าshared_ptr_unsynchronizedวัตถุจะไม่ถูกแชร์ระหว่างเธรดโดยไม่มีการซิงโครไนซ์ที่ผู้ใช้ระบุเพิ่มเติม

แน่นอนว่านี่ไม่สามารถพกพาได้อย่างสมบูรณ์ แต่บางครั้งก็ไม่เป็นไร ด้วยตัวประมวลผลล่วงหน้าที่ถูกต้องแฮ็กโค้ดของคุณจะยังคงทำงานได้ดีกับการใช้งานอื่น ๆ หากshared_ptr_unsynchronized<T>เป็นนามแฝงสำหรับshared_ptr<T>GCC ก็จะเร็วขึ้นเล็กน้อย


หากคุณใช้ GCC ก่อน 4.9 คุณสามารถใช้สิ่งนั้นได้โดยการเพิ่ม_Sp_counted_base<_S_single>ความเชี่ยวชาญเฉพาะทางให้กับโค้ดของคุณเอง (และทำให้มั่นใจว่าจะไม่มีใครสร้างอินสแตนซ์__shared_ptr<T, _S_single>โดยไม่รวมความเชี่ยวชาญพิเศษเพื่อหลีกเลี่ยงการละเมิด ODR) การเพิ่มความเชี่ยวชาญพิเศษstdประเภทดังกล่าวนั้นไม่ได้กำหนดไว้ในทางเทคนิค แต่จะ ทำงานในทางปฏิบัติเพราะในกรณีนี้ไม่มีความแตกต่างระหว่างฉันเพิ่มความเชี่ยวชาญพิเศษใน GCC หรือคุณเพิ่มลงในรหัสของคุณเอง


2
แค่สงสัยว่าตัวอย่างของชื่อแทนเทมเพลตมีการพิมพ์ผิดหรือเปล่า คือฉันคิดว่ามันควรจะอ่าน shared_ptr_unsynchronized = std :: __ shared_ptr <. บังเอิญฉันได้ทดสอบสิ่งนี้ในวันนี้ร่วมกับ std :: __ enable_shared_from_this และ std :: __ mild_ptr และดูเหมือนว่าจะทำงานได้ดี (gcc 4.9 และ gcc 5.2) ฉันจะสร้างโปรไฟล์ / แยกชิ้นส่วนในไม่ช้าเพื่อดูว่าการดำเนินการของอะตอมถูกข้ามไปหรือไม่
Carl Cook

รายละเอียดสุดเจ๋ง! เร็ว ๆ นี้ผมต้องเผชิญกับปัญหาที่อธิบายไว้ในคำถามนี้ว่าในที่สุดก็ทำให้ผมมองเข้าไปในซอร์สโค้ดของstd::shared_ptr, std::__shared_ptr, __default_lock_policyและเช่น คำตอบนี้ยืนยันสิ่งที่ฉันเข้าใจจากรหัส
Nawaz

21

คำถามที่สองของฉันคือเหตุใด std :: shared_ptr เวอร์ชันที่ไม่ใช่อะตอมจึงไม่มีให้ใน C ++ 11 (สมมติว่ามีสาเหตุ)

เราสามารถถามได้อย่างง่ายดายว่าเหตุใดจึงไม่มีตัวชี้ที่ล่วงล้ำหรือตัวชี้ที่ใช้ร่วมกันรูปแบบอื่น ๆ ที่เป็นไปได้

การออกแบบที่shared_ptrตกทอดมาจาก Boost เป็นการสร้างภาษากลางขั้นต่ำของตัวชี้อัจฉริยะ โดยทั่วไปแล้วคุณสามารถดึงมันลงมาจากผนังแล้วใช้มันได้ เป็นสิ่งที่มักจะถูกนำไปใช้กับแอปพลิเคชันที่หลากหลาย คุณสามารถวางไว้ในอินเทอร์เฟซและโอกาสที่คนดียินดีจะใช้

เธรดมี แต่จะแพร่หลายมากขึ้นในอนาคต อันที่จริงเมื่อเวลาผ่านไปโดยทั่วไปการทำเกลียวจะเป็นหนึ่งในวิธีการหลักในการบรรลุประสิทธิภาพ การกำหนดให้ตัวชี้อัจฉริยะขั้นพื้นฐานทำค่าต่ำสุดที่จำเป็นเพื่อรองรับเธรดช่วยอำนวยความสะดวกในความเป็นจริงนี้

การทิ้งสมาร์ทพอยน์เตอร์ครึ่งโหลที่มีการเปลี่ยนแปลงเล็กน้อยระหว่างตัวชี้เหล่านี้ลงในมาตรฐานหรือที่แย่กว่านั้นคือสมาร์ทพอยน์เตอร์ที่อิงตามนโยบายจะแย่ ทุกคนจะเลือกตัวชี้ที่พวกเขาชอบที่สุดและยอมแพ้คนอื่น ๆ ทั้งหมด ไม่มีใครสามารถสื่อสารกับใครได้อีก มันก็เหมือนกับสถานการณ์ปัจจุบันที่มีสตริง C ++ ซึ่งทุกคนมีประเภทของตัวเอง แย่ลงเท่านั้นเนื่องจากการทำงานร่วมกันกับสตริงนั้นง่ายกว่าการทำงานร่วมกันระหว่างคลาสตัวชี้อัจฉริยะ

Boost และโดยการขยายคณะกรรมการเลือกตัวชี้อัจฉริยะที่เฉพาะเจาะจงเพื่อใช้ มันให้ความสมดุลของคุณสมบัติและใช้กันอย่างแพร่หลายในทางปฏิบัติ

std::vectorมีความไร้ประสิทธิภาพเมื่อเทียบกับอาร์เรย์เปล่าในบางกรณีเช่นกัน มีข้อ จำกัด บางประการ การใช้งานบางอย่างต้องการ จำกัด ขนาดของ a vectorโดยไม่ต้องใช้ตัวจัดสรรการขว้าง อย่างไรก็ตามคณะกรรมการไม่ได้ออกแบบvectorให้เป็นทุกอย่างสำหรับทุกคน ได้รับการออกแบบให้เป็นค่าเริ่มต้นที่ดีสำหรับแอปพลิเคชันส่วนใหญ่ ผู้ที่ไม่สามารถทำงานได้เพียงแค่เขียนทางเลือกที่เหมาะกับความต้องการของพวกเขา

เช่นเดียวกับที่คุณสามารถทำได้สำหรับตัวชี้อัจฉริยะหากshared_ptrปรมาณูเป็นภาระ จากนั้นอีกครั้งหนึ่งอาจพิจารณาไม่ลอกเลียนแบบมากเกินไป


7
+1 สำหรับ "เราอาจพิจารณาว่าไม่ได้คัดลอกมากเกินไป"
Ali

หากคุณเคยเชื่อมต่อกับโปรไฟล์คุณเป็นคนพิเศษและคุณสามารถปรับแต่งข้อโต้แย้งดังที่กล่าวมาได้ หากคุณไม่มีข้อกำหนดในการปฏิบัติงานที่ยากที่จะปฏิบัติตามคุณไม่ควรใช้ C ++ การโต้เถียงอย่างที่คุณทำเป็นวิธีที่ดีในการทำให้ C ++ ถูกประจานในระดับสากลโดยทุกคนที่สนใจในประสิทธิภาพสูงหรือเวลาแฝงต่ำนี่คือเหตุผลที่โปรแกรมเมอร์เกมไม่ใช้ STL เพิ่มหรือแม้แต่ข้อยกเว้น
Hans Malherbe

เพื่อความชัดเจนฉันคิดว่าคำพูดที่อยู่ด้านบนของคำตอบของคุณควรอ่านว่า "ทำไมstd :: shared_ptr เวอร์ชันที่ไม่ใช่อะตอมจึงมีให้ใน C ++ 11"
Charles Savoie

4

ฉันกำลังเตรียมคุยเรื่อง shared_ptr ในที่ทำงาน ฉันใช้บูสต์ shared_ptr ที่แก้ไขแล้วโดยหลีกเลี่ยง malloc แยกต่างหาก (เช่นเดียวกับที่ make_shared ทำได้) และพารามิเตอร์เทมเพลตสำหรับนโยบายการล็อกเช่น shared_ptr_unsynchronized ที่กล่าวถึงข้างต้น ฉันใช้โปรแกรมจาก

http://flyingfrogblog.blogspot.hk/2011/01/boosts-sharedptr-up-to-10-slower-than.html

เป็นการทดสอบหลังจากล้างสำเนา shared_ptr ที่ไม่จำเป็น โปรแกรมใช้เธรดหลักเท่านั้นและอาร์กิวเมนต์ทดสอบจะแสดงขึ้น env การทดสอบคือโน้ตบุ๊กที่ใช้ linuxmint 14 นี่คือเวลาที่ใช้เป็นวินาที:

ทดสอบการตั้งค่าการทำงานเพิ่ม (1.49) std ด้วย make_shared modified boost
mt- ไม่ปลอดภัย (11) 11.9 9 / 11.5 (- อ่านต่อ) 8.4  
อะตอม (11) 13.6 12.4 13.0  
mt- ไม่ปลอดภัย (12) 113.5 85.8 / 108.9 (-pthread on) 81.5  
อะตอม (12) 126.0 109.1 123.6  

เฉพาะเวอร์ชัน 'std' เท่านั้นที่ใช้ -std = cxx11 และ -pthread อาจเปลี่ยน lock_policy ในคลาส g ++ __shared_ptr

จากตัวเลขเหล่านี้ฉันเห็นผลกระทบของคำแนะนำอะตอมต่อการเพิ่มประสิทธิภาพโค้ด กรณีทดสอบไม่ได้ใช้คอนเทนเนอร์ C ++ ใด ๆ แต่vector<shared_ptr<some_small_POD>>มีแนวโน้มที่จะได้รับผลกระทบหากวัตถุไม่ต้องการการป้องกันเธรด Boost มีความทุกข์น้อยลงเนื่องจาก malloc เพิ่มเติมกำลัง จำกัด จำนวน inlining และ code optimizaton

ฉันยังไม่พบเครื่องที่มีคอร์เพียงพอที่จะทดสอบความสามารถในการปรับขนาดของคำแนะนำเกี่ยวกับอะตอม แต่การใช้ std :: shared_ptr เมื่อจำเป็นเท่านั้นน่าจะดีกว่า


4

Boost ให้สิ่งshared_ptrที่ไม่ใช่อะตอม เรียกว่าlocal_shared_ptrและสามารถพบได้ในไลบรารีตัวชี้อัจฉริยะของการเพิ่ม


+1 สำหรับการตอบกลับสั้น ๆ ที่มั่นคงพร้อมการอ้างอิงที่ดี แต่ตัวชี้ประเภทนี้มีราคาแพง - ทั้งในแง่ของหน่วยความจำและรันไทม์เนื่องจากมีการกำหนดทิศทางพิเศษอีกระดับหนึ่ง (local-> shared-> ptr vs shared-> ptr)
Red.Wave

@ Red.Wave คุณสามารถอธิบายความหมายของการกำหนดทิศทางและผลกระทบต่อประสิทธิภาพได้อย่างไร? คุณหมายความว่ามันshared_ptrมีเคาน์เตอร์อยู่แล้วแม้ว่าจะเป็นของท้องถิ่น? หรือคุณหมายความว่ามีปัญหาอื่นอีกหรือไม่? เอกสารกล่าวว่าความแตกต่างเพียงอย่างเดียวคือสิ่งนี้ไม่ใช่ปรมาณู
นักฟิสิกส์ควอนตัม

ทุก ptr ในเครื่องจะนับและอ้างอิงถึง ptr ที่แชร์ดั้งเดิม ดังนั้นการเข้าถึงพอยน์ตี้ขั้นสุดท้ายจะต้องมีการ derefrence จาก local ไปยัง ptr ที่ใช้ร่วมกันซึ่งจากนั้นจะ derefrence ไปยัง pointee ดังนั้นจึงมีอีกหนึ่งทิศทางที่ซ้อนกันไปยัง indirections จาก ptr ที่ใช้ร่วมกัน และนั่นทำให้ค่าใช้จ่ายเพิ่มขึ้น
Red.Wave

@ Red.Wave คุณเอาข้อมูลนี้มาจากไหน? สิ่งนี้: "ดังนั้นการเข้าถึงพอยน์ตี้ขั้นสุดท้ายจึงจำเป็นต้องมีการยกเลิกการอ้างอิงจาก local ไปยัง ptr ที่ใช้ร่วมกัน" จำเป็นต้องมีการอ้างอิง ฉันไม่พบสิ่งนั้นในเอกสารบูสต์ อีกครั้งสิ่งที่ฉันเห็นในเอกสารคือมันบอกlocal_shared_ptrและshared_ptrเหมือนกันยกเว้นปรมาณู ฉันสนใจอย่างแท้จริงที่จะค้นหาว่าสิ่งที่คุณพูดนั้นเป็นความจริงหรือไม่เพราะฉันใช้local_shared_ptrในแอปพลิเคชันที่ต้องการประสิทธิภาพสูง
นักฟิสิกส์ควอนตัม

3
@ Red.Wave หากคุณดูซอร์สโค้ดจริงgithub.com/boostorg/smart_ptr/blob/…คุณจะเห็นว่าไม่มีสองทิศทาง ย่อหน้านี้ในเอกสารเป็นเพียงแบบจำลองทางจิต
Ilya Popov
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.