ฉันรู้ว่าอินไลน์เป็นคำใบ้หรือคำขอให้คอมไพเลอร์และมันใช้เพื่อหลีกเลี่ยงค่าใช้จ่ายในการโทรฟังก์ชั่น
ดังนั้นสิ่งที่พื้นฐานหนึ่งสามารถกำหนดได้ว่าฟังก์ชั่นเป็นตัวเลือกสำหรับการอินไลน์หรือไม่? ในกรณีใดที่หนึ่งควรหลีกเลี่ยงการอินไลน์
ฉันรู้ว่าอินไลน์เป็นคำใบ้หรือคำขอให้คอมไพเลอร์และมันใช้เพื่อหลีกเลี่ยงค่าใช้จ่ายในการโทรฟังก์ชั่น
ดังนั้นสิ่งที่พื้นฐานหนึ่งสามารถกำหนดได้ว่าฟังก์ชั่นเป็นตัวเลือกสำหรับการอินไลน์หรือไม่? ในกรณีใดที่หนึ่งควรหลีกเลี่ยงการอินไลน์
คำตอบ:
การหลีกเลี่ยงค่าใช้จ่ายในการเรียกใช้ฟังก์ชันเป็นเพียงครึ่งเดียวของเรื่องราว
ทำ:
inline
แทน#define
inline
: โค้ดที่เร็วขึ้นและ executables เล็ก (โอกาสที่จะอยู่ในแคชของโค้ด)ไม่ได้:
เมื่อพัฒนาห้องสมุดเพื่อที่จะทำให้ชั้นเรียนขยายได้ในอนาคตคุณควร:
โปรดจำไว้ว่าinline
คำหลักนั้นเป็นคำใบ้ของคอมไพเลอร์: คอมไพเลอร์อาจตัดสินใจที่จะไม่อินไลน์ฟังก์ชั่นและมันสามารถตัดสินใจที่จะอินไลน์ฟังก์ชั่นที่ไม่ได้ทำเครื่องหมายinline
ในสถานที่แรก ฉันมักจะหลีกเลี่ยงการทำเครื่องหมายฟังก์ชั่นinline
(นอกเหนือจากบางทีเมื่อเขียนฟังก์ชั่นที่เล็กมาก ๆ )
เกี่ยวกับประสิทธิภาพวิธีการที่ชาญฉลาดคือ (เช่นเคย) เพื่อทำโปรไฟล์แอปพลิเคชันจากนั้นinline
ชุดของฟังก์ชันที่แสดงถึงคอขวดในที่สุด
อ้างอิง:
แก้ไข: Bjarne Stroustrup, ภาษา C ++ การเขียนโปรแกรม:
inline
ฟังก์ชั่นที่สามารถกำหนดให้เป็น ตัวอย่างเช่น:
inline int fac(int n)
{
return (n < 2) ? 1 : n * fac(n-1);
}
ตัว
inline
ระบุเป็นคำใบ้ของคอมไพเลอร์ที่ควรพยายามสร้างรหัสสำหรับการโทรfac()
แบบอินไลน์แทนที่จะวางโค้ดสำหรับฟังก์ชั่นหนึ่งครั้งแล้วเรียกผ่านกลไกการเรียกฟังก์ชันตามปกติ เรียบเรียงฉลาดสามารถสร้างอย่างต่อเนื่องสำหรับการโทร720
fac(6)
ความเป็นไปได้ของฟังก์ชั่นอินไลน์แบบเรียกซ้ำร่วมกันฟังก์ชั่นอินไลน์ที่ชดเชยหรือไม่ขึ้นอยู่กับอินพุต ฯลฯ ทำให้ไม่สามารถรับประกันได้ว่าการเรียกใช้inline
ฟังก์ชันทุกครั้งจะถูกขีดเส้นใต้ ระดับของความฉลาดของคอมไพเลอร์ไม่สามารถออกกฏหมายดังนั้นหนึ่งคอมไพเลอร์อาจสร้าง720
อีกและอีกสายเรียกยกเลิก6 * fac(5)
inlinedfac(6)
เพื่อให้การอินไลน์เป็นไปได้หากไม่มีการรวบรวมและเชื่อมโยงสิ่งอำนวยความสะดวกที่ฉลาดผิดปกติคำจำกัดความ - และไม่ใช่แค่การประกาศ - ของฟังก์ชันอินไลน์ต้องอยู่ในขอบเขต (§9.2) ตัวระบุ
inline
ไม่มีผลต่อความหมายของฟังก์ชัน โดยเฉพาะอย่างยิ่งฟังก์ชั่นแบบอินไลน์ยังคงมีที่อยู่ที่ไม่ซ้ำกันและมีstatic
ตัวแปร (§7.1.2) ของฟังก์ชั่นอินไลน์
EDIT2: ISO-IEC 14882-1998, 7.1.2 ตัวระบุฟังก์ชั่น
การประกาศฟังก์ชัน (8.3.5, 9.3, 11.4) พร้อมตัว
inline
ระบุประกาศฟังก์ชันอินไลน์ ตัวระบุอินไลน์บ่งชี้ถึงการใช้งานที่การทดแทนแบบอินไลน์ของร่างกายของฟังก์ชั่นที่จุดของการโทรจะเป็นที่ต้องการกับกลไกการเรียกใช้ฟังก์ชั่นปกติ การดำเนินการไม่จำเป็นต้องดำเนินการทดแทนแบบอินไลน์นี้ ณ จุดที่เรียก; อย่างไรก็ตามแม้ว่าจะมีการละเว้นการแทนที่แบบอินไลน์นี้กฎอื่น ๆ สำหรับฟังก์ชั่นแบบอินไลน์ที่กำหนดโดย 7.1.2 จะยังคงได้รับการเคารพ
inline
เป็นมากกว่าคำใบ้ของคอมไพเลอร์ มันเปลี่ยนกฎภาษาเกี่ยวกับคำจำกัดความหลาย ๆ นอกจากนี้การมีข้อมูลสแตติกไม่ใช่เหตุผลเหล็กหล่อเพื่อหลีกเลี่ยงการอินไลน์ฟังก์ชัน การดำเนินการมีหน้าที่ในการจัดสรรวัตถุคงที่เดียวสำหรับแต่ละฟังก์ชั่นคงที่ไม่ว่าจะมีการประกาศฟังก์ชั่นinline
หรือไม่ ชั้นเรียนยังคงขยายได้ถ้าพวกเขามีตัวสร้างแบบอินไลน์และ destructors เสมือน และ braces destructor ที่ว่างเปล่าเป็นฟังก์ชั่นเสมือนหนึ่งที่บางครั้งก็เป็นความคิดที่ดีที่จะออกจากอินไลน์
inline
ผลลัพธ์คือฟังก์ชั่นไม่ได้รับการอินไลน์: คุณจ่ายราคาสำหรับการโทรและหน่วยการแปลแต่ละหน่วยที่รวมและการเรียกใช้ฟังก์ชันได้รับสำเนาของรหัสและตัวแปรสแตติกของตัวเอง เหตุผลที่ไม่ inlining ก่อสร้างและ destructors เมื่อมีการพัฒนาห้องสมุดให้เป็นความเข้ากันได้กับไบนารีรุ่นอนาคตของห้องสมุดของคุณ
inline
ฟังก์ชั่นที่ไม่สามารถ inline ถ้าคอมไพเลอร์รู้สึกเหมือนมัน และinline
ฟังก์ชั่นจะไม่ถูกแทรกหากคอมไพเลอร์ตัดสินใจที่จะไม่อินไลน์มัน ดังที่ชาร์ลส์เบลีย์พูดมันเปลี่ยนกฎภาษา แทนที่จะคิดว่ามันเป็นการเพิ่มประสิทธิภาพคำแนะนำมันถูกต้องมากกว่าที่จะคิดว่ามันเป็นแนวคิดที่แตกต่างอย่างสิ้นเชิง inline
คำหลักบอกคอมไพเลอร์เพื่อให้คำจำกัดความหลายและไม่มีอะไรอื่น การปรับให้เหมาะสมที่สุด "inlining" สามารถใช้ได้กับเกือบทุกฟังก์ชั่นไม่ว่าจะทำเครื่องหมายไว้หรือไม่inline
ก็ตาม
inline
เพื่อรับฟังก์ชั่นอินไลน์ บางครั้งเราต้องการผลประโยชน์อื่น ๆ เช่นได้รับรอบ ODR
inline
มีน้อยมากที่จะทำกับการเพิ่มประสิทธิภาพ inline
เป็นคำสั่งสำหรับคอมไพเลอร์ที่จะไม่ทำให้เกิดข้อผิดพลาดถ้าฟังก์ชั่นที่ให้คำจำกัดความเกิดขึ้นหลายครั้งในโปรแกรมและสัญญาว่าคำจำกัดความจะเกิดขึ้นในการแปลทุกครั้งที่มีการใช้งานและทุกที่ที่มันปรากฏ
จากกฎข้างต้นinline
เหมาะสำหรับฟังก์ชั่นสั้น ๆ ที่ร่างกายไม่จำเป็นต้องใช้รวมถึงการพึ่งพาพิเศษสำหรับสิ่งที่ต้องการประกาศ ทุกครั้งที่พบความผิดพลาดจะต้องมีการแยกวิเคราะห์และรหัสสำหรับร่างกายของมันอาจถูกสร้างขึ้นเพื่อให้มันหมายถึงค่าใช้จ่ายคอมไพเลอร์มากกว่าฟังก์ชั่นที่กำหนดเพียงครั้งเดียวในไฟล์ต้นฉบับเดียว
คอมไพเลอร์อาจอินไลน์ (เช่นแทนที่การเรียกไปยังฟังก์ชันด้วยรหัสที่ดำเนินการของฟังก์ชันนั้น) การเรียกใช้ฟังก์ชันใด ๆ ที่เลือกไว้ มันเคยเป็นกรณีที่มัน "ชัดแจ้ง" ไม่สามารถอินไลน์ฟังก์ชั่นที่ไม่ได้ประกาศในหน่วยการแปลเดียวกันกับการโทร แต่ด้วยการใช้การเพิ่มประสิทธิภาพของเวลาลิงค์ที่เพิ่มขึ้นแม้ว่ามันจะไม่เป็นจริงในขณะนี้ ความจริงที่เท่าเทียมกันคือข้อเท็จจริงที่ว่าฟังก์ชั่นที่ทำเครื่องหมายไว้inline
อาจไม่ได้ถูกแทรกไว้
inline
คำหลักอย่างไร และเรื่องบังเอิญที่มีความสุขคืออะไร?
การบอกให้คอมไพเลอร์ทำงานแบบอินไลน์เป็นการปรับให้เหมาะสมและกฎที่สำคัญที่สุดของการปรับให้เหมาะสมคือการปรับให้เหมาะสมก่อนกำหนดเป็นรากของความชั่วร้ายทั้งหมด เขียนรหัสที่ชัดเจนเสมอ (โดยใช้อัลกอริธึมที่มีประสิทธิภาพ) จากนั้นทำโปรไฟล์โปรแกรมของคุณและปรับฟังก์ชั่นที่ใช้เวลานานเกินไป
หากคุณพบว่าฟังก์ชั่นบางอย่างนั้นสั้นและเรียบง่ายและมันถูกเรียกว่าหมื่นครั้งในวงในที่แน่นหนามันอาจจะเป็นตัวเลือกที่ดี
คุณอาจประหลาดใจแม้ว่า - คอมไพเลอร์ C ++ หลายคนจะอินไลน์ฟังก์ชั่นเล็ก ๆ ให้คุณโดยอัตโนมัติและพวกเขาอาจเพิกเฉยต่อคำขออินไลน์ของคุณเช่นกัน
/FAcs
ใน Visual Studio -s
ใน GCC) เพื่อดูว่ามันทำอะไร จากประสบการณ์ของฉันคอมไพเลอร์ทั้งสองมีน้ำหนักคำหลักอินไลน์ค่อนข้างมาก
inline
คำหลักน้ำหนัก g ++ หรือ VC เลย นั่นคือถ้าคุณเห็นฟังก์ชั่นที่ถูก inline และลบinline
specifier จากมันก็จะยังคงได้รับการ inline หากคุณมีตัวอย่างที่เฉพาะเจาะจงของสิ่งที่ตรงกันข้ามโปรดแบ่งปันพวกเขา!
inline
ขัดขวางคำว่า "รหัสที่ชัดเจน"? คำหลักใน "การเพิ่มประสิทธิภาพก่อนวัยอันควร" คือก่อนกำหนดไม่ใช่การเพิ่มประสิทธิภาพ การบอกว่าคุณควรหลีกเลี่ยงการเพิ่มประสิทธิภาพอย่างจริงจัง *เป็นเพียงขยะ จุดอ้างอิงนั้นคือคุณควรหลีกเลี่ยงการปรับให้เหมาะสมที่อาจไม่จำเป็นและมีผลข้างเคียงที่เป็นอันตรายต่อรหัส (เช่นทำให้สามารถบำรุงรักษาได้น้อยลง) ฉันล้มเหลวในการดูว่าinline
คำหลักจะทำให้รหัสสามารถบำรุงรักษาได้น้อยลงหรือวิธีที่อาจเป็นอันตรายต่อการเพิ่มลงในฟังก์ชัน
inline
วิธีที่ดีที่สุดที่จะพบคือไปที่โปรไฟล์โปรแกรมของคุณและทำเครื่องหมายฟังก์ชั่นขนาดเล็กที่ได้รับการเรียกจำนวนมากครั้งและการเผาไหม้ผ่านรอบการทำงานว่า คำหลักที่นี่คือ "เล็ก" - เมื่อค่าใช้จ่ายในการเรียกใช้ฟังก์ชั่นเล็กน้อยเมื่อเทียบกับเวลาที่ใช้ในฟังก์ชั่นก็ไม่มีประโยชน์ที่จะอินไลน์พวกเขา
การใช้งานอื่น ๆ ที่ฉันแนะนำคือถ้าคุณมีฟังก์ชั่นเล็ก ๆ ที่เรียกว่าโค้ดที่มีประสิทธิภาพที่สำคัญบ่อยครั้งมากพอที่จะทำให้แคชพลาด อีกครั้งเป็นสิ่งที่ผู้สร้างโปรไฟล์สามารถบอกคุณได้
การเพิ่มประสิทธิภาพก่อนวัยอันควรเป็นรากฐานของความชั่วร้ายทั้งหมด!
ตามกฎของหัวแม่มือฉันมักจะแทรก "getters" และ "setters" เท่านั้น เมื่อโค้ดทำงานและมีความเสถียรการทำโปรไฟล์สามารถแสดงว่าฟังก์ชันใดที่จะได้ประโยชน์จากการอินไลน์
ในทางกลับกันคอมไพเลอร์สมัยใหม่ส่วนใหญ่มีอัลกอริธึมการปรับให้เหมาะสมค่อนข้างดี
Reasuming - เขียนฟังก์ชั่นหนึ่งซับในบรรทัดและกังวลเกี่ยวกับผู้อื่นในภายหลัง
ฟังก์ชั่นแบบอินไลน์อาจปรับปรุงประสิทธิภาพโค้ดของคุณโดยไม่จำเป็นต้องกดอาร์กิวเมนต์ลงในสแต็ก หากฟังก์ชันที่เป็นปัญหาอยู่ในส่วนที่สำคัญของรหัสของคุณคุณควรตัดสินใจแบบอินไลน์ไม่ได้เป็นการตัดสินใจแบบอินไลน์ในส่วนการเพิ่มประสิทธิภาพของโครงการของคุณ
คุณสามารถอ่านเพิ่มเติมเกี่ยวกับอินไลน์ในc ++ faq
ฉันมักจะใช้ฟังก์ชั่นแบบอินไลน์ไม่ได้เป็นการเพิ่มประสิทธิภาพ แต่เพื่อให้โค้ดอ่านง่ายขึ้น บางครั้งรหัสตัวเองสั้นลงและง่ายต่อการเข้าใจมากกว่าความคิดเห็นชื่อที่สื่อความหมายเป็นต้นตัวอย่างเช่น
void IncreaseCount() { freeInstancesCnt++; }
ผู้อ่านรู้ได้ทันทีถึงความหมายที่สมบูรณ์ของรหัส
ฉันมักจะปฏิบัติตามกฎง่ายๆที่ฉันทำฟังก์ชั่นที่มีงบง่ายๆ 3-4 แบบเป็นแบบอินไลน์ แต่มันก็เป็นเรื่องดีที่จะจำไว้ว่ามันเป็นเพียงคำใบ้ของคอมไพเลอร์ การเรียกครั้งสุดท้ายเพื่อให้อินไลน์หรือไม่ถูกรวบรวมโดยคอมไพเลอร์เท่านั้น หากมีมากกว่างบจำนวนมากเหล่านี้ฉันจะไม่ประกาศแบบอินไลน์เช่นเดียวกับคอมไพเลอร์โง่มันอาจนำไปสู่การขยายตัวของรหัส
วิธีที่ดีที่สุดคือการตรวจสอบและเปรียบเทียบคำแนะนำที่สร้างขึ้นสำหรับแบบอินไลน์และไม่อินไลน์ inline
แต่ก็เป็นที่ปลอดภัยเสมอที่จะละเว้น การใช้inline
อาจนำไปสู่ปัญหาที่คุณไม่ต้องการ
เมื่อตัดสินใจว่าจะใช้แบบอินไลน์ฉันมักจะคำนึงถึงความคิดต่อไปนี้: ในการแฝงหน่วยความจำของเครื่องที่ทันสมัยอาจเป็นคอขวดที่ใหญ่กว่าการคำนวณแบบดิบ ฟังก์ชั่นอินไลน์ที่เรียกว่ามักจะเป็นที่รู้จักกันในการขยายขนาดที่ปฏิบัติการ นอกจากนี้ฟังก์ชั่นดังกล่าวสามารถเก็บไว้ในแคชรหัสของ CPU ซึ่งจะลดจำนวนของแคชที่หายไปเมื่อจำเป็นต้องเข้าถึงรหัสนั้น
ดังนั้นคุณต้องตัดสินใจด้วยตัวเอง: การเพิ่มหรือลดขนาดของรหัสเครื่องที่สร้างไว้ใช่หรือไม่ มีโอกาสมากที่การเรียกฟังก์ชั่นนี้จะทำให้แคชพลาด ถ้ามันเต็มไปด้วยรหัสฉันจะบอกว่าโอกาสนั้นสูง ถ้ามันถูก จำกัด ไว้ที่การวนรอบที่แคบเพียงครั้งเดียวโอกาสนั้นก็จะต่ำลง
ฉันมักจะใช้อินไลน์ในกรณีที่ฉันร้อง อย่างไรก็ตามที่คุณมีความกังวลอย่างแท้จริงเกี่ยวกับประสิทธิภาพการทำโปรไฟล์เป็นสิ่งจำเป็น นอกจากนี้คุณอาจต้องการตรวจสอบว่าคอมไพเลอร์ใช้คำใบ้จริงหรือไม่
นอกจากนี้วิธีการแบบอินไลน์มีผลข้างเคียงที่รุนแรงเมื่อดูแลโครงการขนาดใหญ่ เมื่อมีการเปลี่ยนแปลงรหัส inline ไฟล์ทั้งหมดที่ใช้มันจะถูกสร้างใหม่โดยอัตโนมัติโดยคอมไพเลอร์ (มันเป็นคอมไพเลอร์ที่ดี) การทำเช่นนี้อาจทำให้คุณเสียเวลาในการพัฒนามาก
เมื่อinline
วิธีการถูกถ่ายโอนไปยังไฟล์ต้นฉบับและไม่ได้ inlined อีกโครงการทั้งหมดจะต้องสร้างใหม่ (อย่างน้อยก็เป็นประสบการณ์ของฉัน) และเมื่อมีการแปลงวิธีการเป็นแบบอินไลน์
inline
หรือไม่ไม่สำคัญ (นอกเหนือโดยไม่ต้องinline
คำหลักที่คุณจะได้รับข้อผิดพลาดลิงเกอร์ - แต่inline
คำหลักไม่เป็นปัญหาที่ก่อให้เกิดการสร้างใหม่มากเกินไป.
ควรใช้ตัวระบุฟังก์ชันอินไลน์เฉพาะเมื่อโค้ดฟังก์ชันมีขนาดเล็กเท่านั้นหากฟังก์ชันมีขนาดใหญ่กว่าคุณควรชอบฟังก์ชั่นปกติเนื่องจากการประหยัดพื้นที่หน่วยความจำนั้นคุ้มค่ากับการเสียสละขนาดเล็กเมื่อเปรียบเทียบกับความเร็วในการประมวลผล
เมื่อคุณคิดว่าโค้ดของคุณมีขนาดเล็กพอที่จะใช้เป็นแบบอินไลน์และจำฟังก์ชันอินไลน์ซ้ำรหัสของคุณและวางมันเป็นฟังก์ชั่นที่เรียกว่าดังนั้นมันอาจจะดีพอที่จะเพิ่มเวลาในการดำเนินการของคุณ คุณไม่สามารถใช้ฟังก์ชั่นแบบอินไลน์เมื่อคุณใช้ฟังก์ชันลูป / สแตติกตัวแปร / เวียนเกิด / สลับ / โกโตะ / เสมือน หมายถึงเสมือนรอจนกว่ารันไทม์และอินไลน์หมายถึงในระหว่างการรวบรวมเพื่อให้พวกเขาไม่สามารถใช้พร้อมกัน
ฉันอ่านคำตอบแล้วเห็นว่ามีบางอย่างขาดหายไป
กฎที่ฉันใช้คือไม่ใช้อินไลน์ยกเว้นว่าฉันต้องการให้เป็นแบบอินไลน์ ดูเหมือนโง่ตอนนี้คำอธิบาย
คอมไพเลอร์ฉลาดพอและฟังก์ชั่นระยะสั้นทำให้อินไลน์เสมอ และไม่ทำให้ฟังก์ชั่นแบบยาวเป็นแบบอินไลน์เว้นแต่โปรแกรมเมอร์จะทำเช่นนั้น
ฉันรู้ว่าอินไลน์เป็นคำใบ้หรือคำขอให้คอมไพเลอร์
อันที่จริงinline
คือคำสั่งสำหรับคอมไพเลอร์มันไม่มีตัวเลือกและหลังจากinline
คำหลักทำให้โค้ดทั้งหมด ดังนั้นคุณไม่สามารถใช้inline
คำหลักและคอมไพเลอร์จะออกแบบรหัสที่สั้นที่สุด
ดังนั้นควรใช้เมื่อinline
ใด
หากต้องการใช้หากคุณต้องการมีรหัสแบบอินไลน์ ฉันรู้เพียงตัวอย่างเดียวเพราะฉันใช้มันในสถานการณ์เดียวเท่านั้น มันคือการตรวจสอบผู้ใช้
เช่นฉันมีฟังก์ชั่นนี้:
inline bool ValidUser(const std::string& username, const std::string& password)
{
//here it is quite long function
}
ไม่ว่าฟังก์ชั่นนี้จะใหญ่แค่ไหนก็ตามเพราะมันทำให้ซอฟต์แวร์แตกได้ยากขึ้น
inline
คือไปที่ C ++ มาใหม่สิ่งที่CFLAGS
จะมาใหม่ Gentoo: ไม่มีการรวบรวมที่มี-O3 -funroll-loops -finline-functions
จะไม่ทำให้ Pentium เก่าของคุณบิน;)