ย้ายการดำเนินงาน (เช่นคอนสตรัคย้าย) ให้std::shared_ptr
มีราคาถูกเช่นที่พวกเขาโดยทั่วไปเป็น"ตัวชี้ขโมย" (จากต้นทางไปยังปลายทาง; จะแม่นยำมากขึ้นบล็อกการควบคุมของรัฐทั้งหมดจะถูก "ขโมย" จากต้นทางไปยังปลายทางรวมทั้งข้อมูลจำนวนการอ้างอิง) .
แต่การคัดลอกการดำเนินการในการstd::shared_ptr
เรียกใช้การเพิ่มจำนวนการอ้างอิงของอะตอม (เช่นไม่ใช่แค่++RefCount
ในRefCount
สมาชิกข้อมูลจำนวนเต็มแต่เช่นการโทรInterlockedIncrement
บน Windows) ซึ่งมีราคาแพงกว่าการขโมยพอยน์เตอร์ / รัฐ
ดังนั้นการวิเคราะห์การเปลี่ยนแปลงการนับการอ้างอิงของกรณีนี้ในรายละเอียด:
// shared_ptr<CompilerInvocation> sp;
compilerInstance.setInvocation(sp);
หากคุณผ่านsp
ค่าจากนั้นคัดลอกภายในCompilerInstance::setInvocation
วิธีการคุณมี:
- เมื่อเข้าสู่วิธีการที่
shared_ptr
มีพารามิเตอร์คัดลอกสร้าง: โทษนับอะตอม เพิ่มขึ้น
- ภายในร่างกายของวิธีการที่คุณคัดลอก
shared_ptr
พารามิเตอร์เข้าไปในข้อมูลสมาชิก: Ref นับอะตอม เพิ่มขึ้น
- เมื่อออกจากวิธีการ
shared_ptr
พารามิเตอร์ destructed: โทษนับอะตอม ลดลง
คุณมีการเพิ่มขึ้นสองครั้งของอะตอมและการลดลงของอะตอมหนึ่งครั้งรวมเป็น ดำเนินการปรมาณูสามครั้ง
แต่ถ้าคุณผ่าน shared_ptr
พารามิเตอร์ตามค่าและจากนั้นstd::move
ภายในเมธอด (ทำอย่างถูกต้องในรหัสของ Clang) คุณมี:
- เมื่อเข้าสู่วิธีการ
shared_ptr
มีพารามิเตอร์คัดลอกสร้าง: โทษนับอะตอม เพิ่มขึ้น
- ภายในร่างกายของวิธีนี้คุณ
std::move
shared_ptr
พารามิเตอร์เข้าไปในข้อมูลสมาชิก: ref นับไม่ไม่เปลี่ยนแปลง! คุณเป็นเพียงการขโมยพอยน์เตอร์ / รัฐ: ไม่มีการดำเนินการนับอะตอมที่มีราคาแพงที่เกี่ยวข้อง
- เมื่อออกจากวิธีการ
shared_ptr
พารามิเตอร์จะถูกทำลาย; แต่เนื่องจากคุณย้ายเข้ามาในขั้นตอนที่ 2 ไม่มีสิ่งใดที่จะทำลายได้เนื่องจากshared_ptr
พารามิเตอร์ไม่ได้ชี้ไปที่สิ่งใดอีกต่อไป ในกรณีนี้ไม่มีการลดลงของอะตอม
บรรทัดด้านล่าง: ในกรณีนี้คุณจะได้รับเพียงหนึ่งโทษนับเพิ่มอะตอมคือเพียงหนึ่งอะตอมการดำเนินงาน
อย่างที่คุณเห็นนี่เป็นดีกว่าการเพิ่มขึ้นสองครั้งของอะตอมบวกหนึ่งการลดลงของอะตอม (สำหรับการดำเนินการปรมาณูทั้งหมดสามครั้ง ) สำหรับกรณีการคัดลอก