ย้ายการดำเนินงาน (เช่นคอนสตรัคย้าย) ให้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::moveshared_ptrพารามิเตอร์เข้าไปในข้อมูลสมาชิก: ref นับไม่ไม่เปลี่ยนแปลง! คุณเป็นเพียงการขโมยพอยน์เตอร์ / รัฐ: ไม่มีการดำเนินการนับอะตอมที่มีราคาแพงที่เกี่ยวข้อง
- เมื่อออกจากวิธีการ
shared_ptrพารามิเตอร์จะถูกทำลาย; แต่เนื่องจากคุณย้ายเข้ามาในขั้นตอนที่ 2 ไม่มีสิ่งใดที่จะทำลายได้เนื่องจากshared_ptrพารามิเตอร์ไม่ได้ชี้ไปที่สิ่งใดอีกต่อไป ในกรณีนี้ไม่มีการลดลงของอะตอม
บรรทัดด้านล่าง: ในกรณีนี้คุณจะได้รับเพียงหนึ่งโทษนับเพิ่มอะตอมคือเพียงหนึ่งอะตอมการดำเนินงาน
อย่างที่คุณเห็นนี่เป็นดีกว่าการเพิ่มขึ้นสองครั้งของอะตอมบวกหนึ่งการลดลงของอะตอม (สำหรับการดำเนินการปรมาณูทั้งหมดสามครั้ง ) สำหรับกรณีการคัดลอก