std :: auto_ptr ถึง std :: unique_ptr


185

กับมาตรฐานใหม่ที่มา (และชิ้นส่วนอยู่แล้วในบางคอมไพเลอร์) รูปแบบใหม่ควรจะเป็นแทน std::unique_ptrstd::auto_ptr

การใช้งานของพวกเขาทับซ้อนกันหรือไม่ (เพื่อให้ฉันสามารถค้นหา / แทนที่ทั่วโลกบนโค้ดของฉัน (ไม่ใช่ว่าฉันจะทำสิ่งนี้ แต่ถ้าฉันทำ)) หรือฉันควรตระหนักถึงความแตกต่างที่ไม่ชัดเจนจากการอ่านเอกสาร?

นอกจากนี้ถ้ามันเป็นแทนโดยตรงทำไมให้มันชื่อใหม่มากกว่าแค่การปรับปรุงstd::auto_ptr?

คำตอบ:


219

คุณไม่สามารถค้นหา / แทนที่ทั่วโลกได้เนื่องจากคุณสามารถคัดลอกauto_ptr(พร้อมกับผลที่ตามมา) แต่unique_ptrสามารถย้ายได้เท่านั้น สิ่งที่ดูเหมือน

std::auto_ptr<int> p(new int);
std::auto_ptr<int> p2 = p; 

จะต้องเป็นอย่างน้อยแบบนี้

std::unique_ptr<int> p(new int);
std::unique_ptr<int> p2 = std::move(p);

ในฐานะที่เป็นความแตกต่างอื่น ๆunique_ptrสามารถจัดการได้อย่างถูกต้องอาร์เรย์ (มันจะเรียกdelete[]ในขณะที่จะพยายามที่จะเรียกร้องauto_ptrdelete


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

7
@jalf: อันที่จริงฉันไม่สามารถนึกถึงตัวอย่างเคาน์เตอร์ที่จะถูกกำหนดอย่างดีด้วย auto_ptrs และ UB ด้วย unique_ptrs
Cubbi

1
ดังนั้นดูเหมือนว่า unique_ptr คือการปรับปรุงของ auto_ptr: สนับสนุนอาร์เรย์และลบความกำกวม
Baiyan Huang

92

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

  • ตัวแปรขอบเขตฟังก์ชั่น:
    ใช้งานได้ 100% ตราบใดที่คุณไม่ผ่านค่านั้นไปยังฟังก์ชันอื่น
  • ประเภทผลตอบแทน: ใช้งาน
    ไม่ได้ 100% แต่ใช้งานได้ 99% ดูเหมือนจะไม่ผิด
  • พารามิเตอร์ฟังก์ชั่นตามค่า:
    100% เข้ากันได้กับหนึ่ง caveat, unique_ptrs จะต้องผ่านการstd::moveโทร อันนี้เรียบง่ายเพราะคอมไพเลอร์จะบ่นถ้าคุณทำไม่ถูก
  • พารามิเตอร์ฟังก์ชั่นโดยการอ้างอิง:
    เข้ากันได้ 100%
  • ตัวแปรสมาชิกคลาส:
    อันนี้ยุ่งยาก std::auto_ptrความหมายของการลอกเลียนแบบนั้นชั่วร้าย หากคลาสไม่อนุญาตให้คัดลอกดังนั้นstd::unique_ptrจะเป็นการแทนที่ อย่างไรก็ตามหากคุณพยายามให้ซีแมนทิกส์การคัดลอกคลาสที่เหมาะสมคุณจะต้องเปลี่ยนstd::auto_ptrรหัสการจัดการ นี่เป็นเรื่องง่ายเนื่องจากคอมไพเลอร์จะบ่นถ้าคุณทำไม่ถูก หากคุณอนุญาตให้คัดลอกคลาสกับstd::auto_ptrสมาชิกโดยไม่ต้องใช้รหัสพิเศษใด ๆ จงทำให้คุณอับอายและโชคดี

ในการสรุปเป็นทิวstd::unique_ptr std::auto_ptrมันไม่อนุญาตให้พฤติกรรมรวบรวมเวลาที่มีมักจะstd::auto_ptrมีข้อผิดพลาดเมื่อใช้ ดังนั้นหากคุณใช้std::auto_ptrด้วยความระมัดระวังก็จำเป็นต้องเปลี่ยนไปใช้std::unique_ptrควรจะง่าย หากคุณเชื่อมั่นในstd::auto_ptrพฤติกรรมแปลก ๆ คุณต้องทำการปรับรหัสของคุณใหม่


8
+1 สำหรับ "คุณต้องปรับรหัสของคุณใหม่" auto_ptrs ดีสำหรับสิ่งที่ 20.4.5 / 3 บอกว่าดีสำหรับ
Cubbi

8
ให้ฉันเพิ่มสิ่งนี้ที่คุณควรแทนที่ auto_ptr โดย unique_ptr ในรหัสของคุณและแก้ไขข้อผิดพลาดในการรวบรวม คุณจะประหลาดใจว่ามีข้อบกพร่องมากมายที่จะเปิดเผย
Bartosz Milewski

36

AFAIK unique_ptrไม่ใช่การแทนที่โดยตรง ข้อบกพร่องที่สำคัญที่แก้ไขได้คือการถ่ายโอนความเป็นเจ้าของโดยนัย

std::auto_ptr<int> a(new int(10)), b;
b = a; //implicitly transfers ownership

std::unique_ptr<int> a(new int(10)), b;
b = std::move(a); //ownership must be transferred explicitly

ในทางตรงกันข้ามunique_ptrจะมีความสามารถใหม่อย่างสมบูรณ์: พวกเขาสามารถเก็บไว้ในภาชนะ


8
สก็อตเมเยอร์สยังกล่าวถึงในรายการ "Effective C ++" (ฉบับที่ 3) รายการที่ 13 (หน้า 64) ที่คอนเทนเนอร์ STL ต้องการให้เนื้อหาแสดงพฤติกรรมการคัดลอก "ปกติ" ดังนั้นจึงauto_ptrไม่อนุญาตให้ใช้คอนเทนเนอร์
Qiang Xu

31

Herb Sutter มีคำอธิบายที่ดีเกี่ยวกับGotW # 89 :

ข้อตกลงกับ auto_ptr คืออะไร auto_ptr มีความโดดเด่นที่สุดในฐานะความพยายามที่กล้าหาญในการสร้างเอกลักษณ์ _ptr ก่อนที่ C ++ จะมีซีแมนทิกส์การย้าย auto_ptr เลิกใช้แล้วและไม่ควรใช้ในรหัสใหม่

หากคุณมี auto_ptr ในฐานรหัสที่มีอยู่เมื่อคุณมีโอกาสลองทำการค้นหาทั่วโลกและแทนที่ auto_ptr เป็น unique_ptr การใช้งานส่วนใหญ่จะใช้งานได้เหมือนกันและอาจแสดงให้เห็น (เป็นข้อผิดพลาดในการคอมไพล์เวลา) หรือแก้ไข (เงียบ ๆ ) ข้อบกพร่องหรือสองอย่างที่คุณไม่เคยรู้มาก่อน

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


ลิงค์ที่ยอดเยี่ยม ขอบคุณมาก!
fotNelton
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.