ส่งคืนตัวชี้อัจฉริยะตามค่า
ดังที่คุณได้กล่าวไว้หากคุณส่งคืนโดยการอ้างอิงคุณจะไม่สามารถเพิ่มจำนวนการอ้างอิงได้อย่างถูกต้องซึ่งจะทำให้เสี่ยงต่อการลบบางสิ่งในเวลาที่ไม่เหมาะสม เพียงอย่างเดียวควรเป็นเหตุผลเพียงพอที่จะไม่ส่งคืนโดยอ้างอิง อินเทอร์เฟซควรมีประสิทธิภาพ
ปัจจุบันความกังวลเรื่องค่าใช้จ่ายเกิดขึ้นเนื่องจากการเพิ่มประสิทธิภาพการคืนค่า (RVO) ดังนั้นคุณจะไม่เกิดลำดับการเพิ่มขึ้น - ลดลงหรืออะไรทำนองนั้นในคอมไพเลอร์สมัยใหม่ ดังนั้นวิธีที่ดีที่สุดในการคืนค่า a shared_ptr
คือเพียงแค่ส่งคืนค่า:
shared_ptr<T> Foo()
{
return shared_ptr<T>();
};
นี่เป็นโอกาส RVO ที่ชัดเจนสำหรับคอมไพเลอร์ C ++ สมัยใหม่ ฉันรู้ว่าคอมไพเลอร์ Visual C ++ ใช้ RVO แม้ว่าจะปิดการปรับให้เหมาะสมทั้งหมด และด้วยความหมายการเคลื่อนที่ของ C ++ 11 ข้อกังวลนี้มีความเกี่ยวข้องน้อยลง (แต่วิธีเดียวที่จะแน่ใจได้คือการกำหนดโปรไฟล์และการทดลอง)
หากคุณยังไม่มั่นใจ Dave Abrahams มีบทความที่โต้แย้งการคืนค่าตามมูลค่า ฉันสร้างข้อมูลโค้ดซ้ำที่นี่ ฉันขอแนะนำให้คุณอ่านบทความทั้งหมด:
ซื่อสัตย์: รหัสต่อไปนี้ทำให้คุณรู้สึกอย่างไร?
std::vector<std::string> get_names();
...
std::vector<std::string> const names = get_names();
ตรงไปตรงมาแม้ว่าฉันควรจะรู้ดีกว่า แต่มันก็ทำให้ฉันกังวล โดยหลักการแล้วเมื่อget_names()
ส่งคืนเราต้องคัดลอก a vector
ของstring
s จากนั้นเราต้องคัดลอกอีกครั้งเมื่อเริ่มต้น
names
และเราต้องทำลายสำเนาแรก หากมี N string
s อยู่ในเวกเตอร์แต่ละสำเนาอาจต้องการการจัดสรรหน่วยความจำ N + 1 มากถึง N + 1 และการเข้าถึงข้อมูลที่ไม่เป็นมิตรกับแคชทั้งหมด> เนื่องจากมีการคัดลอกเนื้อหาสตริง
แทนที่จะเผชิญหน้ากับความวิตกกังวลแบบนั้นฉันมักจะกลับไปใช้การอ้างอิงแบบพาสบายเพื่อหลีกเลี่ยงการทำสำเนาที่ไม่จำเป็น
get_names(std::vector<std::string>& out_param );
...
std::vector<std::string> names;
get_names( names );
น่าเสียดายที่แนวทางนี้ยังห่างไกลจากอุดมคติ
- รหัสเพิ่มขึ้น 150%
- เราต้องลดลง
const
เพราะเรากำลังกลายพันธุ์ชื่อ
- เนื่องจากโปรแกรมเมอร์ที่ใช้งานได้ต้องการเตือนเราการกลายพันธุ์ทำให้รหัสมีความซับซ้อนมากขึ้นในการให้เหตุผลโดยการบ่อนทำลายความโปร่งใสในการอ้างอิงและการให้เหตุผลที่เท่าเทียมกัน
- เราไม่มีความหมายเชิงคุณค่าที่เข้มงวดสำหรับชื่ออีกต่อไป
แต่จำเป็นจริงๆหรือที่จะทำให้โค้ดของเรายุ่งเหยิงเพื่อให้ได้ประสิทธิภาพ โชคดีที่คำตอบกลายเป็นไม่ (และโดยเฉพาะอย่างยิ่งถ้าคุณใช้ C ++ 0x)