ความถูกต้องของรหัสที่คุณเขียนไม่ควรขึ้นอยู่กับการปรับให้เหมาะสม มันควรจะส่งออกผลลัพธ์ที่ถูกต้องเมื่อดำเนินการใน C ++ "เครื่องเสมือน" ที่พวกเขาใช้ในสเปค
อย่างไรก็ตามสิ่งที่คุณพูดถึงเป็นคำถามที่มีประสิทธิภาพมากกว่า รหัสของคุณจะทำงานได้ดีขึ้นหากปรับให้เหมาะสมด้วยคอมไพเลอร์ปรับแต่ง RVO ให้เหมาะสม ไม่เป็นไรเพราะเหตุผลทั้งหมดชี้ให้เห็นในคำตอบอื่น ๆ
อย่างไรก็ตามหากคุณต้องการการเพิ่มประสิทธิภาพนี้ (เช่นถ้าตัวสร้างการคัดลอกจะทำให้รหัสของคุณล้มเหลว) ตอนนี้คุณอยู่ที่การแปลของคอมไพเลอร์
ฉันคิดว่าตัวอย่างที่ดีที่สุดในเรื่องนี้ในทางปฏิบัติของฉันคือการปรับให้เหมาะสมหาง:
int sillyAdd(int a, int b)
{
if (b == 0)
return a;
return sillyAdd(a + 1, b - 1);
}
มันเป็นตัวอย่างที่งี่เง่า แต่มันแสดงให้เห็นถึงการเรียกแบบหางโดยที่ฟังก์ชั่นนั้นถูกเรียกซ้ำในตอนท้ายของฟังก์ชั่น เครื่องเสมือน C ++ จะแสดงให้เห็นว่ารหัสนี้ทำงานอย่างถูกต้องแม้ว่าฉันอาจทำให้เกิดความสับสนเล็กน้อยว่าทำไมฉันจึงต้องใส่ใจกับการเขียนรูทีนเพิ่มเติมดังกล่าวในตอนแรก อย่างไรก็ตามในการใช้งานจริงของ C ++ เรามีสแต็กและมีพื้นที่ จำกัด หากทำไปเรื่อย ๆ ฟังก์ชันนี้จะต้องผลักb + 1
เฟรมสแต็กอย่างน้อยลงในสแต็กเช่นเดียวกับที่เพิ่มเข้าไป ถ้าฉันต้องการคำนวณsillyAdd(5, 7)
นี่ไม่ใช่เรื่องใหญ่ ถ้าฉันต้องการคำนวณsillyAdd(0, 1000000000)
ฉันอาจมีปัญหาในการก่อให้เกิด StackOverflow (และไม่ใช่ประเภทที่ดี )
อย่างไรก็ตามเราสามารถเห็นได้ว่าเมื่อเราไปถึงบรรทัดสุดท้ายที่ส่งคืนเราจะทำทุกอย่างในสแต็กเฟรมปัจจุบัน เราไม่จำเป็นต้องเก็บมันไว้รอบ ๆ การปรับการเรียกท้ายให้คุณ "นำ" เฟรมสแต็คที่มีอยู่กลับมาใช้ใหม่สำหรับฟังก์ชั่นถัดไป ด้วยวิธีนี้เราจะต้องกองกรอบ 1 b+1
มากกว่า (เรายังต้องทำการบวกและลบออกทั้งหมดที่โง่ แต่พวกเขาไม่ได้ใช้พื้นที่มากขึ้น) ผลการเพิ่มประสิทธิภาพจะเปลี่ยนรหัสเป็น:
int sillyAdd(int a, int b)
{
begin:
if (b == 0)
return a;
// return sillyAdd(a + 1, b - 1);
a = a + 1;
b = b - 1;
goto begin;
}
ในบางภาษาข้อกำหนดในการเพิ่มประสิทธิภาพการโทรหางจะต้องระบุไว้อย่างชัดเจน C ++ ไม่ใช่หนึ่งในนั้น ฉันไม่สามารถพึ่งพาคอมไพเลอร์ C ++ เพื่อรับรู้ถึงโอกาสในการเพิ่มประสิทธิภาพการโทรหางนี้ได้เว้นแต่ฉันจะไปเป็นกรณี ๆ ไป ด้วย Visual Studio รุ่นของฉันเวอร์ชันที่วางจำหน่ายจะทำการปรับแต่ง tail call ให้เหมาะสม แต่เวอร์ชันการดีบักไม่ได้ (โดยการออกแบบ)
เพราะฉะนั้นมันก็จะไม่ดีสำหรับผมที่จะขึ้นอยู่กับsillyAdd(0, 1000000000)
ความสามารถในการคำนวณ