คุณควรส่งคืนตามมูลค่า
มาตรฐานมีคุณลักษณะเฉพาะในการปรับปรุงประสิทธิภาพของการส่งคืนตามมูลค่า เรียกว่า "copy elision" และโดยเฉพาะอย่างยิ่งในกรณีนี้คือ "named return value optimization (NRVO)"
คอมไพเลอร์ไม่จำเป็นต้องใช้มัน แต่จากนั้นคอมไพเลอร์อีกครั้งก็ไม่จำเป็นต้องใช้ฟังก์ชัน inlining (หรือทำการเพิ่มประสิทธิภาพใด ๆ เลย) แต่ประสิทธิภาพของไลบรารีมาตรฐานอาจค่อนข้างแย่หากคอมไพเลอร์ไม่ปรับให้เหมาะสมและคอมไพเลอร์ที่จริงจังทั้งหมดใช้อินไลน์และ NRVO (และการเพิ่มประสิทธิภาพอื่น ๆ )
เมื่อใช้ NRVO จะไม่มีการคัดลอกในรหัสต่อไปนี้:
std::vector<int> f() {
std::vector<int> result;
... populate the vector ...
return result;
}
std::vector<int> myvec = f();
แต่ผู้ใช้อาจต้องการทำสิ่งนี้:
std::vector<int> myvec;
... some time later ...
myvec = f();
การคัดลอกการคัดลอกไม่ได้ป้องกันการคัดลอกที่นี่เนื่องจากเป็นการมอบหมายงานแทนที่จะเป็นการเริ่มต้น อย่างไรก็ตามคุณควรยังคงกลับมาด้วยค่า ใน C ++ 11 งานจะได้รับการปรับให้เหมาะสมโดยสิ่งที่แตกต่างกันเรียกว่า "move semantics" ใน C ++ 03 โค้ดข้างต้นทำให้เกิดการคัดลอกและแม้ว่าในทางทฤษฎีเครื่องมือเพิ่มประสิทธิภาพอาจหลีกเลี่ยงได้ แต่ในทางปฏิบัติมันยากเกินไป ดังนั้นmyvec = f()
ใน C ++ 03 คุณควรเขียนสิ่งนี้:
std::vector<int> myvec;
... some time later ...
f().swap(myvec);
มีอีกทางเลือกหนึ่งคือการนำเสนออินเทอร์เฟซที่ยืดหยุ่นมากขึ้นให้กับผู้ใช้:
template <typename OutputIterator> void f(OutputIterator it) {
... write elements to the iterator like this ...
*it++ = 0;
*it++ = 1;
}
จากนั้นคุณยังสามารถรองรับอินเทอร์เฟซแบบเวกเตอร์ที่มีอยู่ได้อีกด้วย:
std::vector<int> f() {
std::vector<int> result;
f(std::back_inserter(result));
return result;
}
ซึ่งอาจมีประสิทธิภาพน้อยกว่ารหัสที่มีอยู่ของคุณหากรหัสที่มีอยู่ของคุณใช้reserve()
ในลักษณะที่ซับซ้อนมากกว่าจำนวนเงินที่กำหนดไว้ล่วงหน้า แต่ถ้าโดยพื้นฐานแล้วรหัสที่มีอยู่ของคุณเรียกpush_back
ใช้เวกเตอร์ซ้ำ ๆ รหัสที่ใช้เทมเพลตนี้ก็น่าจะดีเช่นกัน
f
?