IMO ทำให้ฟังก์ชันมีขอบเขตของหน่วยการแปลเท่านั้น
อะไรคือความแตกต่างระหว่างฟังก์ชัน "static" และ "static inline"
ทำไมinlineต้องใส่ไว้ในไฟล์ส่วนหัวไม่ใช่ใน.cไฟล์?
IMO ทำให้ฟังก์ชันมีขอบเขตของหน่วยการแปลเท่านั้น
อะไรคือความแตกต่างระหว่างฟังก์ชัน "static" และ "static inline"
ทำไมinlineต้องใส่ไว้ในไฟล์ส่วนหัวไม่ใช่ใน.cไฟล์?
คำตอบ:
inlineสั่งให้คอมไพลเลอร์พยายามฝังเนื้อหาฟังก์ชันลงในโค้ดการเรียกแทนที่จะเรียกใช้งานจริง
สำหรับฟังก์ชั่นขนาดเล็กที่เรียกบ่อยซึ่งสามารถสร้างความแตกต่างด้านประสิทธิภาพได้มาก
อย่างไรก็ตามนี่เป็นเพียง "คำใบ้" และคอมไพเลอร์อาจเพิกเฉยและคอมไพเลอร์ส่วนใหญ่จะพยายาม "อินไลน์" แม้ว่าจะไม่ได้ใช้คีย์เวิร์ดก็ตามซึ่งเป็นส่วนหนึ่งของการเพิ่มประสิทธิภาพหากเป็นไปได้
ตัวอย่างเช่น:
static int Inc(int i) {return i+1};
.... // some code
int i;
.... // some more code
for (i=0; i<999999; i = Inc(i)) {/*do something here*/};
การวนซ้ำแบบแน่นนี้จะเรียกใช้ฟังก์ชันในการวนซ้ำแต่ละครั้งและเนื้อหาของฟังก์ชันนั้นน้อยกว่าโค้ดที่คอมไพลเลอร์ต้องใส่เพื่อทำการเรียก inlineโดยพื้นฐานแล้วจะสั่งให้คอมไพเลอร์แปลงโค้ดด้านบนให้เทียบเท่ากับ:
int i;
....
for (i=0; i<999999; i = i+1) { /* do something here */};
ข้ามการเรียกใช้ฟังก์ชันจริงและย้อนกลับ
เห็นได้ชัดว่านี่เป็นตัวอย่างเพื่อแสดงประเด็นไม่ใช่โค้ดจริง
staticหมายถึงขอบเขต ในภาษา C หมายความว่าฟังก์ชัน / ตัวแปรสามารถใช้ได้ภายในหน่วยการแปลเดียวกันเท่านั้น
static(มีหรือไม่มีinline) สามารถอยู่ในส่วนหัวได้อย่างสมบูรณ์แบบดูเหตุผลว่าทำไมไม่ เทมเพลตสำหรับ C ++ คำถามนี้เกี่ยวกับ C.
inlineจึงเป็นรูปแบบที่ดี imo
inlineไม่ได้สั่งให้คอมไพเลอร์พยายามใด ๆ ในการซับใน เป็นเพียงการอนุญาตให้โปรแกรมเมอร์รวมเนื้อความฟังก์ชันไว้ในหน่วยการแปลหลายหน่วยโดยไม่ละเมิด ODR ผลข้างเคียงของสิ่งนี้คือทำให้คอมไพเลอร์เป็นไปได้เมื่อมันจะอินไลน์ฟังก์ชันจะทำสิ่งนี้ได้
ตามค่าเริ่มต้นคำจำกัดความแบบอินไลน์ใช้ได้เฉพาะในหน่วยการแปลปัจจุบัน
ถ้าคลาสหน่วยเก็บคือexternตัวระบุจะมีการเชื่อมโยงภายนอกและนิยามอินไลน์ยังให้นิยามภายนอกด้วย
ถ้าคลาสหน่วยเก็บคือstaticตัวระบุจะมีการเชื่อมโยงภายในและนิยามอินไลน์จะมองไม่เห็นในหน่วยการแปลอื่น
หากไม่ได้ระบุคลาสหน่วยเก็บข้อมูลนิยามแบบอินไลน์จะปรากฏในหน่วยการแปลปัจจุบันเท่านั้น แต่ตัวระบุยังคงมีการเชื่อมโยงภายนอกและต้องระบุนิยามภายนอกในหน่วยการแปลอื่น คอมไพลเลอร์มีอิสระที่จะใช้อินไลน์หรือนิยามภายนอกหากฟังก์ชันถูกเรียกใช้ภายในหน่วยการแปลปัจจุบัน
เนื่องจากคอมไพลเลอร์มีอิสระในการอินไลน์ (และไม่อยู่ในบรรทัด) ฟังก์ชันใด ๆ ที่มีความหมายที่มองเห็นได้ในหน่วยการแปลปัจจุบัน (และด้วยการเพิ่มประสิทธิภาพเวลาลิงก์แม้ในหน่วยการแปลที่แตกต่างกันแม้ว่ามาตรฐาน C จะไม่ได้คำนึงถึง นั้น) เพื่อวัตถุประสงค์ในทางปฏิบัติส่วนใหญ่ไม่มีความแตกต่างระหว่างstaticและstatic inlineนิยามฟังก์ชัน
ตัวinlineระบุ (เช่นregisterคลาสหน่วยเก็บข้อมูล) เป็นเพียงคำใบ้ของคอมไพเลอร์เท่านั้นและคอมไพเลอร์มีอิสระที่จะเพิกเฉยโดยสิ้นเชิง คอมไพเลอร์ที่ไม่ปรับให้เหมาะสมตามมาตรฐานจะต้องให้เกียรติผลข้างเคียงของมันเท่านั้นและการเพิ่มประสิทธิภาพคอมไพเลอร์จะทำการเพิ่มประสิทธิภาพเหล่านี้โดยมีหรือไม่มีคำใบ้ที่ชัดเจน
inlineและregisterไม่ไร้ประโยชน์แม้ว่าจะสั่งให้คอมไพเลอร์โยนข้อผิดพลาดเมื่อโปรแกรมเมอร์เขียนโค้ดที่จะทำให้การปรับให้เหมาะสมเป็นไปไม่ได้: inlineนิยามภายนอกไม่สามารถอ้างอิงตัวระบุที่มีการเชื่อมโยงภายในได้ (เนื่องจากสิ่งเหล่านี้จะไม่สามารถใช้ได้ในหน่วยการแปลอื่น) หรือกำหนดตัวแปรภายในที่ปรับเปลี่ยนได้โดยมีระยะเวลาการจัดเก็บแบบคงที่ (เนื่องจากสิ่งเหล่านี้จะไม่แชร์สถานะกับหน่วยการแปล) และคุณไม่สามารถใช้ที่อยู่ของregisterตัวแปรที่มีคุณสมบัติเหมาะสมได้
โดยส่วนตัวแล้วฉันใช้หลักการนี้เพื่อทำเครื่องหมายstaticคำจำกัดความของฟังก์ชันภายในส่วนหัวด้วยinlineเนื่องจากเหตุผลหลักในการใส่คำจำกัดความของฟังก์ชันในไฟล์ส่วนหัวคือการทำให้ไม่สามารถใช้งานได้
โดยทั่วไปฉันใช้คำจำกัดความของstatic inlineฟังก์ชันและstatic constอ็อบเจ็กต์นอกเหนือจากการexternประกาศภายในส่วนหัวเท่านั้น
ฉันไม่เคยเขียนinlineฟังก์ชันที่มีคลาสพื้นที่เก็บข้อมูลที่แตกต่างจากstatic.
inlineราวกับว่ามันถูกนำไปใช้กับการอินไลน์จริงๆนั้นทำให้เข้าใจผิดและเนื้อหาไม่ถูกต้อง ไม่มีคอมไพเลอร์ที่ทันสมัยใช้เป็นคำใบ้ในการอินไลน์หรือต้องการเพื่อเปิดใช้งานการแทรกในฟังก์ชัน
static static inlineทั้งสองทำให้ความหมายมองไม่เห็นในหน่วยการแปลอื่น ๆ อะไรคือเหตุผลที่สมเหตุสมผลที่จะเขียนstatic inlineแทนstatic?
จากประสบการณ์ของฉันกับ GCC ฉันรู้staticและstatic inlineแตกต่างกันในวิธีที่คอมไพเลอร์ออกคำเตือนเกี่ยวกับฟังก์ชันที่ไม่ได้ใช้ แม่นยำมากขึ้นเมื่อคุณประกาศstaticฟังก์ชั่นและมันไม่ได้ถูกใช้ในหน่วยแปลปัจจุบันเตือนผลิตแล้วคอมไพเลอร์เกี่ยวกับฟังก์ชั่นที่ไม่ได้ใช้ static inlineแต่คุณสามารถยับยั้งการเตือนว่ามีการเปลี่ยนไป
ดังนั้นฉันมักคิดว่าstaticควรใช้ในหน่วยการแปลและได้รับประโยชน์จากคอมไพเลอร์ตรวจสอบพิเศษเพื่อค้นหาฟังก์ชันที่ไม่ได้ใช้ และstatic inlineควรใช้ในไฟล์ส่วนหัวเพื่อจัดเตรียมฟังก์ชันที่สามารถเรียงกันได้ (เนื่องจากไม่มีการเชื่อมโยงภายนอก) โดยไม่ต้องออกคำเตือน
น่าเสียดายที่ฉันไม่พบหลักฐานใด ๆ สำหรับตรรกะนั้น แม้แต่จากเอกสาร GCC ฉันก็ไม่สามารถสรุปได้ว่าinlineยับยั้งคำเตือนเกี่ยวกับฟังก์ชันที่ไม่ได้ใช้ ฉันจะขอบคุณถ้ามีคนแชร์ลิงก์ไปยังคำอธิบายนั้น
warning: unused function 'function' [clang-diagnostic-unused-function]สำหรับstatic inlineฟังก์ชันเมื่อสร้างด้วยclang-tidy(v8.0.1) ซึ่งใช้ในหน่วยการแปลอื่น แต่แน่นอนว่านี่เป็นหนึ่งในคำอธิบายและเหตุผลที่ดีที่สุดในการรวมstatic& inline!
ใน C staticหมายถึงฟังก์ชันหรือตัวแปรที่คุณกำหนดสามารถใช้ได้เฉพาะในไฟล์นี้ (เช่นหน่วยคอมไพล์)
ดังนั้นstatic inlineหมายถึงฟังก์ชันอินไลน์ที่สามารถใช้ได้ในไฟล์นี้เท่านั้น
แก้ไข:
หน่วยคอมไพล์ควรเป็นหน่วยการแปล
the compile unitเป็นสิ่งที่ฉันเขียนด้วยความผิดพลาดไม่มีสิ่งนั้นคำศัพท์ที่แท้จริงคือtranslation unit
ความแตกต่างอย่างหนึ่งที่ไม่ได้อยู่ที่ระดับภาษา แต่เป็นระดับการนำไปใช้งานที่ได้รับความนิยม: gcc บางเวอร์ชันจะลบstatic inlineฟังก์ชันที่ไม่ได้อ้างอิงออกจากเอาต์พุตตามค่าเริ่มต้น แต่จะยังคงใช้staticฟังก์ชันธรรมดาแม้ว่าจะไม่ได้อ้างอิงก็ตาม ฉันไม่แน่ใจว่ารุ่นนี้ แต่จากมุมมองในทางปฏิบัติมันหมายความว่ามันอาจจะเป็นความคิดที่ดีที่จะมักจะใช้inlineสำหรับstaticฟังก์ชั่นในส่วนหัว
inlineคำจำกัดความล่ะ? คุณไม่ได้ใช้มันเพื่อexternฟังก์ชั่นหรือไม่?
attribute((used))และการใช้งานเพื่ออนุญาตให้ asm อ้างอิงstaticฟังก์ชันและข้อมูลที่ไม่ได้อ้างอิงเป็นอย่างอื่น
staticหมายถึงขอบเขต ในภาษา C หมายความว่าฟังก์ชัน / ตัวแปรสามารถใช้ได้ภายในหน่วยการแปลเดียวกันเท่านั้น