หากคุณต้องการประสิทธิภาพให้ส่งค่าถ้าคุณเก็บไว้
สมมติว่าคุณมีฟังก์ชันที่เรียกว่า "เรียกใช้สิ่งนี้ในเธรด UI"
std::future<void> run_in_ui_thread( std::function<void()> )
ซึ่งรันโค้ดบางอย่างในเธรด "ui" จากนั้นส่งสัญญาณfuture
เมื่อเสร็จแล้ว (มีประโยชน์ในกรอบ UI ที่เธรด UI คือตำแหน่งที่คุณควรยุ่งกับองค์ประกอบ UI)
เรามีสองลายเซ็นต์ที่เรากำลังพิจารณา:
std::future<void> run_in_ui_thread( std::function<void()> ) // (A)
std::future<void> run_in_ui_thread( std::function<void()> const& ) // (B)
ตอนนี้เราน่าจะใช้สิ่งเหล่านี้ดังนี้:
run_in_ui_thread( [=]{
// code goes here
} ).wait();
ซึ่งจะสร้างการปิดนิรนาม (แลมบ์ดา) สร้างstd::function
ออกมาส่งผ่านไปยังrun_in_ui_thread
ฟังก์ชั่นจากนั้นรอให้มันเสร็จสิ้นการทำงานในเธรดหลัก
ในกรณีที่ (A) ที่ถูกสร้างโดยตรงจากแลมบ์ดาของเราซึ่งถูกนำมาใช้แล้วภายในstd::function
run_in_ui_thread
แลมบ์ดานั้นmove
เข้าสู่std::function
ดังนั้นสถานะเคลื่อนย้ายใด ๆ จะถูกดำเนินการอย่างมีประสิทธิภาพ
ในกรณีที่สองชั่วคราวstd::function
ถูกสร้างขึ้นแลมบ์ดาเป็นmove
วันที่เป็นมันแล้วว่าชั่วคราวจะถูกใช้โดยการอ้างอิงภายในstd::function
run_in_ui_thread
จนถึงตอนนี้ดีมาก - พวกเขาสองคนทำงานได้เหมือนกัน ยกเว้นrun_in_ui_thread
จะทำสำเนาของอาร์กิวเมนต์ฟังก์ชั่นเพื่อส่งไปยังเธรด UI เพื่อดำเนินการ! (มันจะกลับมาก่อนที่มันจะเสร็จสิ้นดังนั้นจึงไม่สามารถใช้การอ้างอิงกับมันได้) สำหรับกรณี (A) เราก็ลงในระยะยาวการจัดเก็บข้อมูล ในกรณี (B), เราถูกบังคับให้คัดลอกmove
std::function
std::function
ร้านค้านั้นทำให้การส่งผ่านโดยมีมูลค่าเหมาะสมที่สุด หากมีความเป็นไปได้ใด ๆ ที่คุณกำลังเก็บสำเนาของstd::function
ผ่านค่า มิฉะนั้นทั้งสองวิธีนั้นจะเทียบเท่ากันโดยประมาณ: ข้อเสียเพียงข้อเดียวคือถ้าคุณใช้วิธีการที่ใหญ่std::function
และมีวิธีย่อยหนึ่งหลังจากใช้วิธีอื่น แบริ่งนั้นจะเป็นที่มีประสิทธิภาพเป็นmove
const&
ขณะนี้มีบางอย่างที่แตกต่างอื่น ๆ std::function
ระหว่างคนทั้งสองที่ส่วนใหญ่จะเตะในถ้าเรามีรัฐถาวรภายใน
สมมติว่าstd::function
เก็บวัตถุบางอย่างด้วยoperator() const
แต่ก็มีmutable
สมาชิกข้อมูลบางส่วนที่มันปรับเปลี่ยน (วิธีหยาบคาย!)
ในstd::function<> const&
กรณีmutable
ที่สมาชิกข้อมูลที่แก้ไขจะเผยแพร่จากการเรียกใช้ฟังก์ชัน ในstd::function<>
กรณีที่พวกเขาจะไม่
นี่เป็นกรณีมุมที่ค่อนข้างแปลก
คุณต้องการที่จะปฏิบัติstd::function
เหมือนคนอื่น ๆ ที่อาจเป็นประเภทที่มีน้ำหนักมากและเคลื่อนย้ายได้อย่างถูก การย้ายมีราคาถูกการคัดลอกอาจมีราคาแพง
sizeof(std::function)
จะไม่เกิน2 * sizeof(size_t)
ซึ่งเป็นขนาดที่เล็กที่สุดที่คุณเคยพิจารณาสำหรับการอ้างอิง const