ฟังก์ชันแบบอินไลน์ใน C ++ ประเด็นคืออะไร?


19

ตามสิ่งที่ฉันอ่านคอมไพเลอร์ไม่จำเป็นต้องแทนที่การเรียกใช้ฟังก์ชันของฟังก์ชันอินไลน์ด้วยร่างกาย แต่จะทำเช่นนั้นหากทำได้ นี่ทำให้ฉันคิด - ทำไมเราถึงมีคำอินไลน์ถ้าเป็นเช่นนั้น? ทำไมไม่ทำฟังก์ชั่นอินไลน์ฟังก์ชั่นทั้งหมดโดยค่าเริ่มต้นและให้คอมไพเลอร์คิดว่ามันสามารถทดแทนการโทรด้วยร่างกายฟังก์ชั่นหรือไม่?


1
ที่นี่ หน้า 6
EpsilonVector

คำตอบ:


40

inlineมาจาก C; มันไม่ใหม่สำหรับ C ++

มีคีย์เวิร์ด C ( registerและinline) ที่ได้รับการออกแบบมาเพื่อให้โปรแกรมเมอร์สามารถช่วยในการเพิ่มประสิทธิภาพโค้ดได้ สิ่งเหล่านี้มักถูกเพิกเฉยในปัจจุบันเนื่องจากคอมไพเลอร์สามารถทำได้ดีกว่าในการลงทะเบียนและตัดสินใจว่าจะทำงานแบบอินไลน์เมื่อใด การสร้างโค้ดในตัวประมวลผลที่ทันสมัยนั้นซับซ้อนกว่าตัวประมวลผลทั่วไปมากกว่ามากเมื่อริตชี่กำลังประดิษฐ์ C.

ตอนนี้ความหมายของคำใน C ++ คือสามารถมีหลายคำจำกัดความที่เหมือนกันและจำเป็นต้องกำหนดในทุกหน่วยการแปลที่ใช้มัน (ในคำอื่น ๆ ที่คุณต้องการเพื่อให้แน่ใจว่าสามารถ inlined.) คุณสามารถมีinlineฟังก์ชั่นในส่วนหัวกับปัญหาใด ๆ inlineและฟังก์ชั่นสมาชิกที่กำหนดไว้ในคำนิยามชั้นเรียนโดยอัตโนมัติได้อย่างมีประสิทธิภาพ


3
+1 inlineสำหรับประวัติความเป็นมา
Tamara Wijsman

11
ฉันค่อนข้างแน่ใจว่าinlineเป็นมาตรฐานใน C ++ ก่อนแม้ว่ามันจะมีอยู่แล้วในฐานะส่วนขยายของผู้ขายใน C .... ใช่ดูเหมือนว่ามันจะถูกเพิ่มไปยังมาตรฐาน C ใน C99
Ben Voigt

@Ben Voigt: คุณพูดถูก ฉันพบมันครั้งแรกใน C.
David Thornley

5
นอกจากนี้โปรดทราบว่าไม่เพียง แต่เป็นประวัติที่ไม่ถูกต้องเท่านั้น แต่กฎสำหรับinlineใน C99 และใหม่กว่านั้นแตกต่างจากกฎสำหรับinlineใน C ++
Alf P. Steinbach

27

แต่เดิมinlineเป็นคำใบ้ที่แข็งแกร่งมากว่าการเรียกใช้ฟังก์ชันควรมีการแทรกไว้

แต่ผลที่ได้รับการรับรองเพียงอย่างเดียวของinlineคือการอนุญาตให้ฟังก์ชันถูกกำหนด (อย่างมีประสิทธิภาพเหมือนกัน) ในหน่วยการแปลหลายหน่วยเช่นคุณวางคำจำกัดความไว้ในไฟล์ส่วนหัว

ทุกวันนี้คอมไพเลอร์บางตัวมีความกระตือรือร้นในการทำตามคำแนะนำแบบอินไลน์เช่น g ++ และคอมไพเลอร์บางตัวก็จริงจังน้อยลงเช่น Visual C ++ แต่ทุกคนต้องปฏิบัติตามการรับประกัน

โชคไม่ดีที่ความหมายทั้งสองนี้ - คำแนะนำการเพิ่มประสิทธิภาพและสิ่งที่เราอาจเรียกว่าคำจำกัดความที่สามารถทิ้งได้ระดับ linker - อยู่กับคำหลักเดียวกันเพราะหมายความว่าคุณไม่สามารถมีหนึ่งโดยไม่มีอื่น

โชคไม่ดีที่inline(หรือดีกว่าเป็นคำหลักแยกต่างหากเกี่ยวกับคำจำกัดความที่ยกเลิกได้) ไม่สามารถนำไปใช้กับข้อมูลได้

ความต้องการข้อมูลระดับที่ถูกทิ้งได้ของ linker เพิ่มขึ้นเนื่องจากโมดูลส่วนหัวเท่านั้นได้รับความนิยมมากขึ้น ยกตัวอย่างเช่นห้องสมุดย่อย Boost หลายแห่งเป็นแบบหัวเท่านั้น

อย่างไรก็ตามสำหรับข้อมูลที่คุณสามารถทำได้ให้ใช้เคล็ดลับเล็กน้อยกับเทมเพลต กำหนดไว้ในเทมเพลตบางคลาสระบุtypedefพารามิเตอร์เทมเพลตvoid(หรืออะไรก็ตาม) นั่นเป็นเพราะกฎข้อกำหนดหนึ่งข้อทำให้เกิดข้อยกเว้นเฉพาะสำหรับเทมเพลต

หมายเหตุ:
¹ inlineตัวแปรจะได้รับการสนับสนุนใน C


1
+1 inlineสำหรับข้อมูลเพิ่มเติมเกี่ยวกับ
Tamara Wijsman

1
" อย่างมีประสิทธิภาพเหมือนกัน " เป็นเงื่อนไขที่ยุ่งยากมากเนื่องจากภาษา C ++ ที่ออกแบบมาไม่ดีพยายามอย่างหนักที่จะทำให้โปรแกรมเมอร์ที่มีความสามารถและระมัดระวังโดยทั่วไปเขียนโค้ดที่สมเหตุสมผล แต่ไม่ได้กำหนดอย่างเป็นทางการซึ่งใช้วัตถุแบบคงที่
curiousguy

6

ทำไมไม่ทำให้ทุกฟังก์ชั่นอินไลน์เป็นค่าเริ่มต้น? เพราะมันเป็นการแลกเปลี่ยนทางวิศวกรรม มี "การเพิ่มประสิทธิภาพ" อย่างน้อยสองประเภท: เร่งความเร็วโปรแกรมและลดขนาด (footprint หน่วยความจำ) ของโปรแกรม การอินไลน์โดยทั่วไปเร่งความเร็วสิ่งต่างๆ มันกำจัดค่าใช้จ่ายในการเรียกใช้ฟังก์ชันหลีกเลี่ยงการกดแล้วดึงพารามิเตอร์จากสแต็ก อย่างไรก็ตามมันยังทำให้ footprint หน่วยความจำของโปรแกรมใหญ่ขึ้นเนื่องจากการเรียกใช้ฟังก์ชันทุกครั้งจะต้องถูกแทนที่ด้วยรหัสเต็มของฟังก์ชั่น เพื่อให้สิ่งต่าง ๆ มีความซับซ้อนยิ่งขึ้นโปรดจำไว้ว่า CPU เก็บหน่วยความจำที่ใช้บ่อย ๆ ไว้ในแคชบน CPU เพื่อการเข้าถึงที่รวดเร็วเป็นพิเศษ หากคุณทำให้อิมเมจหน่วยความจำของโปรแกรมใหญ่พอโปรแกรมของคุณจะไม่สามารถใช้แคชได้อย่างมีประสิทธิภาพและในกรณีที่เลวร้ายที่สุดการอินไลน์ซับอาจทำให้โปรแกรมของคุณช้าลง


5
แต่คอมไพเลอร์สามารถ (และทำ!) คิดสิ่งนี้ดีกว่าโปรแกรมเมอร์โดยทั่วไป ดังนั้นนี่ไม่ใช่อาร์กิวเมนต์ที่ถูกต้อง
Konrad Rudolph

" ทุกการเรียกใช้ฟังก์ชันต้องถูกแทนที่ด้วยรหัสเต็มของฟังก์ชั่น " และฟังก์ชั่นอินไลน์ไม่ใช่ฟังก์ชั่นที่ไม่มีการเรียงลำดับการโทรและรหัสแอสเซมบลีของฟังก์ชั่นถูกแทนที่ ฟังก์ชั่นอินไลน์รวบรวมในสถานที่โดยการนำอินไลน์รหัสระดับสูงระดับสูง ที่ช่วยให้คอมไพเลอร์ปฏิบัติต่อร่างกายของฟังก์ชันได้อย่างมีประสิทธิภาพในฐานะที่เป็นมาโครที่สะอาด (มาโครแบบใหม่คืออันที่ไม่มีมาโครของมาโคร C ตัวประมวลผลล่วงหน้า) โดยมีการปรับให้เหมาะสมมากมาย
curiousguy

3

เพื่อทำความเข้าใจ "อินไลน์" คุณต้องเข้าใจประวัติศาสตร์และชีวิตเป็นอย่างไรเมื่อ 20 ปีก่อนและ 30 ปี

เรากำลังเขียนโค้ดบนคอมพิวเตอร์ที่มีหน่วยความจำน้อยดังนั้นจึงเป็นไปไม่ได้ที่คอมไพเลอร์จะประมวลผลโค้ดทั้งหมดที่ประกอบเป็นโปรแกรมในครั้งเดียว คอมไพเลอร์ก็ช้ามากดังนั้นคุณไม่ต้องการที่จะคอมไพล์โค้ดที่ไม่ได้เปลี่ยน - ใช้เวลา 24 ชั่วโมง (บนคอมพิวเตอร์ที่มีราคาสูงกว่ารถยนต์ระดับบนสุด) เพื่อคอมไพล์รหัสทั้งหมดเป็นเรื่องปกติสำหรับบางโครงการฉัน ทำงานใน

ดังนั้นไฟล์โค้ดแต่ละไฟล์จะถูกคอมไพล์แยกกันเป็นไฟล์อ็อบเจ็กต์ แต่ละอ็อบเจ็กต์ไฟล์เริ่มต้นด้วยรายการของฟังก์ชันทั้งหมดที่มีอยู่พร้อมกับ "ที่อยู่" ของฟังก์ชัน อ็อบเจ็กต์ไฟล์ยังมีรายการฟังก์ชันทั้งหมดที่ถูกเรียกในไฟล์อ็อบเจ็กต์อื่น ๆ พร้อมกับตำแหน่งของการโทร

ลิงเกอร์ครั้งแรกที่จะอ่านไฟล์ทั้งหมดวัตถุและสร้างรายชื่อของฟังก์ชั่นทั้งหมดที่พวกเขาส่งออกพร้อมกับไฟล์พวกเขาอยู่ในและที่อยู่ที่นั่น จากนั้นจะอ่านไฟล์ออบเจ็กต์ทั้งหมดอีกครั้งแล้วส่งออกไปยังไฟล์โปรแกรมในขณะที่อัพเดตการเรียกใช้ฟังก์ชัน "ภายนอก" ทั้งหมดด้วยที่อยู่ของฟังก์ชั่น

ตัวเชื่อมโยงไม่ได้เปลี่ยนแปลงหรือปรับแต่งรหัสเครื่องที่ผลิตโดยคอมไพเลอร์ในลักษณะอื่นใดนอกจากแก้ไขการอ้างอิงถึงการเรียกใช้ฟังก์ชันภายนอก ตัวเชื่อมโยงเป็นส่วนหนึ่งของระบบปฏิบัติการและคอมไพเลอร์ส่วนใหญ่มาก่อน เมื่อมีคนเขียนคอมไพเลอร์ใหม่พวกเขาจำเป็นต้องใช้มันเพื่อทำงานกับลิงเกอร์ปัจจุบันและเพื่อที่จะสามารถลิงค์ไปยังไฟล์วัตถุปัจจุบันมิฉะนั้นจะไม่สามารถทำการเรียกระบบได้

คอมไพเลอร์เท่านั้นที่เห็นรหัสในไฟล์“ .c” หรือ“ .cpp” ซึ่งรวบรวมไว้พร้อมกับไฟล์ส่วนหัวทั้งหมด ดังนั้นจึงไม่สามารถปรับให้เหมาะสมตามรหัสในไฟล์“ .c” หรือ“ .cpp” อื่น ๆ

คีย์เวิร์ด“ inline” อนุญาตให้เนื้อความของฟังก์ชัน (เมธอด) ถูกกำหนดไว้ในไฟล์ส่วนหัวดังนั้นการอนุญาตให้คอมไพเลอร์ใช้ประโยชน์จากรหัสของฟังก์ชันในขณะที่คอมไพล์โค้ดที่เรียกมัน ตัวอย่างเช่นสมมติว่าคุณมีคลาสคอลเลกชันที่กำหนดไว้ในไฟล์ anther .cpp คลาสนี้จะมีเมธอด“ isEmpty” ซึ่งมีโค้ดหนึ่งบรรทัดจะมีการเร่งความเร็วสูงของโปรแกรมที่เป็นผลลัพธ์ถ้าแทนที่จะเรียกใช้ฟังก์ชัน การเรียกใช้ฟังก์ชันถูกแทนที่ด้วยหนึ่งบรรทัดนี้

คำหลัก "inline" ถูกมองว่าเป็นวิธี "ถูกและง่าย" ในการอนุญาตให้มีการห่อหุ้มข้อมูลในขณะที่หลีกเลี่ยงค่าใช้จ่ายในการเรียกใช้ฟังก์ชั่นโดยที่โปรแกรมเมอร์จำนวนมากจะเข้าถึงฟิลด์ส่วนตัวของวัตถุ (มาโครที่โค้ด "inlining" ที่แย่กว่านั้นคือซึ่งเป็นเรื่องธรรมดาในเวลานั้น)

ทุกวันนี้“ ลิงเกอร์” ทำการเพิ่มประสิทธิภาพของโค้ดจำนวนมากและมักจะเขียนโดยทีมบางคนในฐานะคอมไพเลอร์ คอมไพเลอร์มักจะตรวจสอบรหัสถูกต้องและ "บีบอัด" มันออกจากงานส่วนใหญ่ของการสร้างรหัสเครื่องไปยังลิงเกอร์


2

มาดูสิ่งที่มาตรฐานพูด (เน้นส่วนที่สำคัญเป็นตัวหนา):

2. การประกาศฟังก์ชั่นที่มีตัวระบุแบบอินไลน์ประกาศฟังก์ชั่นแบบอินไลน์ ตัวระบุอินไลน์บ่งชี้ถึงการใช้งานที่การทดแทนแบบอินไลน์ของร่างกายของฟังก์ชั่นที่จุดของการโทรจะเป็นที่ต้องการกับกลไกการเรียกใช้ฟังก์ชั่นปกติ การดำเนินการไม่จำเป็นต้องดำเนินการทดแทนแบบอินไลน์ที่จุดโทร; อย่างไรก็ตามแม้ว่าการละเว้นการแทนที่แบบอินไลน์นี้จะยังคงเคารพกฎอื่น ๆ สำหรับฟังก์ชั่นแบบอินไลน์

- มาตรฐาน C ++, ISO / IEC 14882: 2003 , 7.1.2 ตัวระบุฟังก์ชั่น [dcl.fct.spec]

ดังนั้นถ้าคุณต้องการแน่ใจคุณควรอ่านเอกสารของคอมไพเลอร์ของคุณ

การฝังทุกสิ่งเป็นความคิดที่ไม่ดีเนื่องจากอาจทำให้รหัสเครื่องซ้ำซ้อน ...

ดังนั้นคุณจะต้องรู้ว่า:

ไม่มีคำตอบง่ายๆคุณต้องเล่นกับมันเพื่อดูว่าอะไรดีที่สุด ไม่ได้ชำระสำหรับคำตอบง่าย ๆ เช่น "ไม่เคยใช้งานinlineฟังก์ชั่น" หรือ "มักจะใช้inlineฟังก์ชั่น" หรือ "การใช้งานinlineฟังก์ชั่นและถ้าหากฟังก์ชั่นน้อยกว่า N บรรทัดของรหัส." กฎขนาดเดียวที่เหมาะกับทุกข้อเหล่านี้อาจเขียนได้ง่าย แต่จะให้ผลลัพธ์ที่ดีที่สุด

- คำถามที่พบบ่อย C ++, ฟังก์ชั่นอินไลน์ , 9.3 inlineฟังก์ชั่นปรับปรุงประสิทธิภาพหรือไม่?


1
สิ่งที่คุณพูดนั้นเป็นความจริง แต่ไม่เกี่ยวข้องเพราะในฐานะโปรแกรมเมอร์ไม่ใช่การตัดสินใจของคุณว่าจะอินไลน์หรือไม่ คุณใส่คำหลักคุณอาจหรืออาจไม่ได้รับฟังก์ชั่นของคุณอินไลน์ คุณไม่ได้ใส่คำหลักคุณยังอาจหรืออาจไม่ได้รับการแทรก มันไม่มีประโยชน์ที่จะมีกฎใด ๆ สำหรับเมื่อคุณใส่คำสำคัญอะไรกับคอมไพเลอร์ที่เป็นคนตัดสินใจจริงๆ
Kate Gregory

มันไม่เกี่ยวข้องกันอย่างไรถ้ามันบอกว่าเหมือนกับคุณ ไม่มีคำตอบที่ง่าย
Tamara Wijsman

มันไม่เกี่ยวข้องเพราะไม่ตอบคำถาม OPs เขาไม่ได้ถามว่า "สิ่งที่อินไลน์ทำ" เขาถามว่า "ประเด็นคืออะไร" และคำตอบของคุณก็จะเน้นย้ำถึงสิ่งที่เราทุกคนรู้แล้วเกี่ยวกับอินไลน์
Davor Ždralo

@ Davor: "จุดคืออะไร" ไม่ปฏิบัติตามคำถามที่พบบ่อยดังนั้นฉันจึงตอบคำถามที่ตั้งขึ้นภายในคำถาม ฉันกำลังบอกจุดของการinlineย้ำความรู้ในขณะที่ OP ดูเหมือนจะพลาดส่วนหนึ่งซึ่งเป็นเหตุผลหลักว่าทำไมเขาไม่ได้รับจุด สำหรับหนึ่งจะได้รับจุดที่เขาจะต้องมีความเข้าใจในสิ่งที่อยู่ใต้จุดนั้น ...
Tamara Wijsman

ทำไมนรกไม่ยึดติดกับคำถามที่พบบ่อย? มาตรฐานอธิบายเกี่ยวกับไวยากรณ์และความหมายของคำหลักแบบอินไลน์และคำถาม OPs คืออะไรวัตถุประสงค์เมื่อใดควรใช้เมื่อใดควรแก้ไขปัญหาใด ฉันไม่เห็นวิธีการที่ไม่เป็นไปตามคำถามที่พบบ่อย
Davor Ždralo

1

ฉันขอให้คุณมีเหตุผลที่ดีสำหรับการใช้คำหลักแบบอินไลน์

บนระบบฝังตัวเช่นเครื่องพิมพ์ตั๋วหรือระบบขนาดเล็กที่คล้ายกัน โปรเซสเซอร์มีข้อ จำกัด มากและการเรียกใช้ฟังก์ชั่น (การเตรียมพารามิเตอร์ฟังก์ชั่นบนสแต็คการโทรดึงข้อมูลจากสแต็คและนำคำตอบกลับมา ฯลฯ ) อาจใช้เวลาหลายมิลลิวินาทีในการดำเนินการ

ให้บอกว่าเวลาโทรนั้นประมาณ 60 มิลลิวินาที (สำหรับการโทรไม่ใช่ฟังก์ชั่นจริง) และคุณมีการวนซ้ำ 50 ครั้ง (การวนซ้ำหรือการโทรซ้ำในทรี)

เวลาในการเลื่อนไปมาและกลับจากการเรียกใช้ฟังก์ชันนั้นจะใช้เวลา 60 * 50 = 3000 (3 วินาที)

หากคุณมีหน่วยความจำคุณจะต้องทำแบบอินไลน์เพื่อประหยัด 3 วินาที

ดังนั้นโดยทั่วไปจะใช้อินไลน์เมื่อคุณต้องการความเร็วในการประมวลผล ในบางโครงการที่ฉันเกี่ยวข้องเวลาเรียกใช้จะนานกว่าเวลาดำเนินการซึ่งเป็นสถานการณ์ปกติเมื่อต้องใช้แบบอินไลน์


เอ๊ะอะไรนะ? การใส่แบบอินไลน์ในโค้ดของคุณไม่ได้หมายความว่าคอมไพเลอร์จะอินไลน์มันจริงๆและการไม่ใส่ไว้ในนั้นก็ไม่ได้หมายความว่ามันจะไม่เป็นเช่นนั้น มันเป็นเพียงคำใบ้ซึ่งส่วนใหญ่ถูกละเว้นโดยคอมไพเลอร์ในปัจจุบัน หากคอมไพเลอร์พบว่ามีประโยชน์ในการอินไลน์มิฉะนั้นจะเป็นไปได้ คุณไม่มีการควบคุมที่แท้จริง OP รู้อยู่แล้วและกำลังถามฉันอ้างว่า: "ประเด็นคืออะไร" ใครเป็นคนให้ +1 กับเรื่องนี้ เป็นทั้งทำให้เข้าใจผิด (หมายถึงคำหลักที่อินไลน์บังคับให้ใช้การอินไลน์) และไม่เกี่ยวข้องกับคำถาม
Davor Ždralo

2
@ Davor Ždraloไม่จำเป็นต้องหยาบคาย ฉันตีความคำถามว่าทำไมฉันจึงควรใช้อินไลน์ จุดของฉันคือการแสดงให้เห็นว่าคุณสามารถรับรหัสได้เร็วขึ้นด้วยราคาหน่วยความจำ ผู้เรียบเรียงแต่ละคนอาจจัดการกับคำสำคัญแบบอินไลน์แตกต่างกันดังนั้นคุณต้องตรวจสอบเอกสารซึ่งฉันไม่ได้พูดถึง เนื่องจากคุณไม่สามารถซื้อหน่วยความจำอินไลน์เหนือค่าหน่วยความจำเพิ่มเติมที่สร้างขึ้นได้จึงเป็นประโยชน์ในการ "แนะนำ" เมื่อใช้ ฉันยังไม่ได้บอกว่ามีการบังคับใช้ไลน์ บางคนพบว่าคำตอบนี้มีประโยชน์สำหรับเขา / เธอและลงคะแนน +1 โปรดเคารพว่าคนอื่นอาจมีประสบการณ์ในระดับอื่นและหาสิ่งที่มีประโยชน์เล็กน้อย
Max Kielland
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.