เป็นไปได้หรือไม่ที่จะใช้ตัวชี้อัจฉริยะเล็กน้อยที่ไม่ได้เป็นเจ้าของไว้เหนือตัวชี้จุดอ่อนมาตรฐาน [ปิด]

ฉันคิดว่าในขณะที่ฉันเข้าใจ เป้าหมายของ std::observer_ptr ฉันคิดว่ามันจะ จะดีถ้าอย่างน้อยมีตัวเลือกสำหรับประเภทตัวชี้ที่คล้ายกันซึ่งรู้ว่าสิ่งที่ชี้ไปนั้นถูกลบไปแล้วหรือไม่ ตัวอย่างเช่น เราอาจมีสิ่งต่อไปนี้

slightly_smart_ptr<Foo> p1(new Foo());
auto p2 = p1;
p1.erase(); // This deletes the foo referred to by p1.
if (p2.expired())
   std::cout << "p2 is expired\n"; // this will fire

วิธีหนึ่งในการบรรลุเป้าหมายนี้ด้วยไลบรารีมาตรฐานปัจจุบันคือ สร้าง shared_ptr เป็น A ในขอบเขตบางอย่างที่จะมีอยู่ตลอดอายุการใช้งานของ A เสมอ อ้างถึง A โดยการส่งอ่อนแอ_ptrs ไปรอบๆ และลบ A เมื่อไม่ต้องการอีกต่อไปโดยการรีเซ็ต shared_ptr อ่อนแอ_ptrs ที่นี่จะมีความหมายพื้นฐานของ observer_ptrs ที่ทราบว่า A ถูกลบไปแล้วหรือไม่ แต่มีปัญหากับแนวทางนี้: จะต้องล็อคอ่อนแอ_ptrs เปลี่ยนให้เป็น shared_ptrs ที่จะใช้ ซึ่งรู้สึกไม่เป็นระเบียบ แต่ที่จริงจังกว่านั้นคือ shared_ptr ถึง A ต้องมีอยู่ที่ไหนสักแห่ง เมื่อผู้ใช้ทุกคนต้องการคือตัวชี้อัจฉริยะเล็กน้อยที่ไม่ได้เป็นเจ้าของ เนื้อหาใด ๆ ผู้ใช้ตกลงที่จะทำลายเนื้อหาด้วยตนเองเมื่อถึงเวลา: ไม่มีการแบ่งปันความเป็นเจ้าของ ดังนั้นจึงเป็นกลิ่นโค้ดสำหรับผู้ใช้ในการสร้าง shared_ptr ในสถานการณ์ดังกล่าว

อย่างไรก็ตาม ฉันไม่สามารถนึกถึงวิธีที่จะซ่อนรายละเอียดของการดำเนินการนี้ได้อย่างมีประสิทธิภาพ

ตัวชี้ดังกล่าวมีอยู่เป็นข้อเสนอหรือในไลบรารีเสริมหรือที่อื่น ๆ หรือไม่?


person jwezorek    schedule 16.08.2019    source แหล่งที่มา
comment
ฉันไม่แน่ใจว่าฉันเข้าใจคำถาม คุณต้องการให้ตัวชี้แบบกำหนดเองของคุณได้รับการแจ้งเตือนเมื่อวัตถุที่ตัวชี้ไปถูกทำลาย โดยไม่คำนึงถึงวิธีการจัดสรรหรือไม่   -  person HolyBlackCat    schedule 16.08.2019
comment
ฉันต้องการประเภทตัวชี้ที่กำหนดเองซึ่งถ้า p1 และ p2 เป็นอินสแตนซ์ของประเภททั้งสองชี้ไปที่ A ถ้าฉัน p1.reset(nullptr) สิ่งนี้จะลบ A - การดำเนินการนี้ไม่จำเป็นต้องถูกเรียกว่ารีเซ็ต แต่คุณได้รับแนวคิด - แล้ว p2.expired() จะเป็นจริง   -  person jwezorek    schedule 16.08.2019
comment
ฟังดูคล้ายกับ QPointer ของ Qt มาก   -  person Jesper Juhl    schedule 16.08.2019
comment
หากิน ไม่มีส่วนเล็กๆ น้อยๆ ว่าทำไมตัวชี้ที่อ่อนแอจึงต้องมีการล็อค คือการที่การจัดสรรไม่ได้รับการปลดปล่อยจากการใช้การจัดสรร หากคุณเพียงต้องการทราบว่าตัวชี้ ณ จุดเวลาที่แน่นอนนี้ถูกต้องหรือไม่? การล็อคมันมากเกินไป แต่ฉันไม่เห็นประเด็นอื่นมากนัก การจัดสรรอาจหายไปทันทีหลังการทดสอบ คุณได้รับการแจ้งเตือนเกี่ยวกับการจัดสรรคืนหรือไม่?   -  person user4581301    schedule 16.08.2019
comment
ฉันไม่เห็นปัญหาในการใช้ shared_ptr และ weak_ptr จริงๆ ไม่ว่าคุณจะออกแบบสิ่งนี้อย่างไร คุณจะต้องล็อควัตถุเพื่อที่พอยน์เตอร์ตัวหนึ่งจะไม่ลบมันในขณะที่อีกอันกำลังใช้งานอยู่   -  person super    schedule 16.08.2019
comment
หากคุณเพียงต้องการทราบว่าตัวชี้ ณ จุดเวลาที่แน่นอนนี้ถูกต้องหรือไม่ การล็อคมันมากเกินไป แต่ฉันไม่เห็นประเด็นอื่นมากนัก --- ฉันหมายถึงว่าถ้าไม่ล็อค มันก็หมายความว่า เล็กน้อย_smart_ptr‹T› จะไม่ปลอดภัยสำหรับเธรด ใช่ไหม? แต่ข้อวิพากษ์วิจารณ์ใหญ่ประการหนึ่งของ shared_ptr คือคุณต้องจ่ายเงินเพื่อความปลอดภัยของเธรดแม้ว่าคุณจะไม่ต้องการก็ตาม   -  person jwezorek    schedule 16.08.2019
comment
@jwezorek ไม่แค่นั้น แต่ if(ptr.valid()) { stuff(); ptr->a; } ฟังก์ชัน stuff() สามารถทำให้ตัวชี้ใช้ไม่ได้ ดังนั้นคุณต้องตรวจสอบก่อนทุกคำสั่ง   -  person Guillaume Racicot    schedule 16.08.2019
comment
สิ่งที่คุณขอนั้นเป็นเรื่องยากที่จะเป็นไปไม่ได้ในกรณีทั่วไป แต่เมื่อไม่มีเธรด (และสมมติว่าคุณไม่ได้เล่นกับการขัดจังหวะมากนัก) คุณเพิ่งจำกัดกรณีการใช้งานเพื่อขจัดปัญหายุ่งยากส่วนใหญ่อย่างแท้จริง ฉันแนะนำให้เพิ่มสิ่งนั้นลงในคำถาม   -  person user4581301    schedule 16.08.2019
comment
ทบทวนเรื่องนั้นสักหน่อย มีคำตอบที่ยอดเยี่ยมสำหรับคำถามนี้ตามคำถามที่เขียนไว้ คุณควรเขียนคำถามใหม่แทนที่จะทำให้คำถามนั้นเป็นโมฆะ   -  person user4581301    schedule 16.08.2019


คำตอบ (2)


ปัญหาของตัวชี้อัจฉริยะดังกล่าวคือมีแนวโน้มที่จะเกิดข้อผิดพลาดมากกว่า std::unique_ptr, T* หรือ std::weak_ptr

เมื่อคุณต้องการทราบว่าตัวชี้ถูกลบจากที่อื่นโดยเจ้าของที่ไม่ซ้ำกันหรือไม่ ในความเป็นจริงคุณต้องเป็นเจ้าของร่วมกันและ std::weak_ptr

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


นอกจากนี้คุณยังมีความขัดแย้งที่ลึกซึ้งยิ่งขึ้น

เมื่อคุณมีพอยน์เตอร์ที่ไม่ซ้ำใคร คุณจะรู้ว่าใครจะลบมัน และคุณจะรู้ว่าใครเป็นเจ้าของ

หากคุณมีโปรแกรมที่ตรวจสอบความถูกต้องของพอยน์เตอร์ขณะรันไทม์ อาจเป็นเพราะโปรแกรมของคุณไม่ทราบสถานะความเป็นเจ้าของทรัพยากร

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

หากคุณมีการเป็นเจ้าของร่วมกัน คุณไม่จำเป็นต้องมีตัวชี้เซิร์ฟเวอร์ที่รู้ว่าถูกลบไปแล้วหรือไม่

ตัวชี้ของคุณไม่จำเป็นต้องมีอยู่แล้ว


ดังนั้น... คุณคิดว่าคุณต้องการพอยน์เตอร์นั้น มันอาจจะมีประโยชน์... คุณจะทำอย่างไร?

คุณต้องตรวจสอบรหัสของคุณ หากมีเจ้าของเพียงรายเดียว ทำไมคุณต้องทราบความถูกต้องของตัวชี้ด้วย ทำไมคุณไม่สามารถถามเจ้าของได้?

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

หากเจ้าของที่ไม่ซ้ำกันของคุณเสียชีวิตในช่วงเวลาที่คาดเดาไม่ได้ (เช่น เจ้าของที่ไม่ซ้ำกันของคุณถูกครอบครองโดยเจ้าของที่ใช้ร่วมกัน) บางทีโครงสร้างของคุณควรตรวจสอบความถูกต้องของเจ้าของที่ใช้ร่วมกันแทน

บางทีโค้ดของคุณที่เรียกใช้ฟังก์ชันที่ต้องการตรวจสอบว่าตัวชี้ยังใช้งานได้หรือไม่ไม่ควรเรียกใช้เมื่อเจ้าของเสียชีวิต

...

และอื่นๆ

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

person Guillaume Racicot    schedule 16.08.2019

ไม่สามารถทำได้โดยทั่วไป

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

ประโยชน์ที่คุณกำลังอธิบายคือคุณประโยชน์ที่มาจากการใช้พอยน์เตอร์อัจฉริยะที่ยังหลงเหลืออยู่ shared_ptr และ weak_ptr สมบูรณ์แบบที่นี่

ไม่มีปัญหาในการล็อค (คุณต้องการสิ่งนี้) และไม่มีปัญหากับการต้องมี shared_ptr ที่ไหนสักแห่ง เพราะแน่นอนว่า บางคน บางแห่งเป็นเจ้าของข้อมูลนั้น หากไม่เป็นเช่นนั้น การออกแบบของคุณจะมีปัญหาใหญ่กว่ามากและคุณกำลังพยายามแฮ็กปัญหาเหล่านั้นด้วยแนวคิดตัวชี้อัจฉริยะที่เสียหายในลักษณะเดียวกันซึ่งจะไม่มีอยู่ในมาตรฐาน

person Lightness Races in Orbit    schedule 16.08.2019