ประโยชน์ของฟังก์ชั่นอินไลน์ใน C ++?


254

ข้อดี / ข้อเสียของการใช้ฟังก์ชั่นอินไลน์ใน C ++ คืออะไร ฉันเห็นว่ามันเพิ่มประสิทธิภาพสำหรับโค้ดที่คอมไพเลอร์ส่งออกเท่านั้น แต่ด้วยคอมไพเลอร์ที่ได้รับการปรับปรุงในปัจจุบัน, ซีพียูเร็ว, หน่วยความจำขนาดใหญ่ ฯลฯ (ไม่เหมือนกับในปี 1980 <ที่หน่วยความจำขาดแคลนมาก วันนี้พวกเขามีข้อดีอย่างไร


48
นี่เป็นหนึ่งในคำถามที่ความรู้ทั่วไปผิด ทุกคนได้ตอบด้วยคำตอบ Comp Sci มาตรฐาน (การทำอินไลน์ช่วยประหยัดค่าใช้จ่ายในการโทร แต่เพิ่มขนาดรหัส) ขยะมูลฝอย มันมีกลไกง่าย ๆ สำหรับคอมไพเลอร์เพื่อใช้การเพิ่มประสิทธิภาพมากขึ้น
Martin York

37
นี่เป็นหนึ่งในคำตอบที่แสดงความคิดเห็น หากคุณไม่ชอบคำตอบใด ๆ ที่โพสต์ให้โพสต์คำตอบของคุณเองและดูว่าจะไปได้อย่างไร
Dave Van den Eynde

10
พื้นฐานของคำถามนี้มีข้อบกพร่อง ฟังก์ชั่นอินไลน์ C ++ มีส่วนเกี่ยวข้องกับคอมไพเลอร์อินไลน์ระหว่างการคอมไพล์ โชคไม่ดีที่inlineเป็นคำหลัก c ++ และการ inlining เป็นเทคนิคการปรับให้เหมาะสมของคอมไพเลอร์ ดูคำถามนี้ " เมื่อใดฉันจึงควรเขียนคำหลักinlineสำหรับฟังก์ชั่น / วิธีการ " สำหรับคำตอบที่ถูกต้อง
deft_code

3
@JoseVega ลิงก์ของคุณมี mangled - ลิงก์ปัจจุบันคือexforsys.com/tutorials/c-plus-plus/inline-functions.html

คำตอบ:


143

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

มันสร้างความแตกต่างอย่างมีนัยสำคัญหรือไม่? ไม่เพียงพอสำหรับฮาร์ดแวร์ที่ทันสมัยสำหรับส่วนใหญ่ แต่มันสามารถสร้างความแตกต่างซึ่งเพียงพอสำหรับบางคน

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

ฉันเห็นสถานการณ์เช่นนี้สร้างความแตกต่างที่ตรวจพบได้:

inline int aplusb_pow2(int a, int b) {
  return (a + b)*(a + b) ;
}

for(int a = 0; a < 900000; ++a)
    for(int b = 0; b < 900000; ++b)
        aplusb_pow2(a, b);

26
อย่างที่ฉันสงสัยว่าการทำอินไลน์ทำให้ไม่มีความแตกต่างด้านบน คอมไพล์ด้วย gcc 4.01 เวอร์ชัน 1 ถูกบังคับให้ใช้การอินไลน์: 48.318u 1.042s 5: 51.39 99.4% 0 + 0k 0 + 0io 0pf + 0w เวอร์ชัน 2 บังคับให้ไม่มีอินไลน์ 348.311u 1.019s 5: 52.31 99.1% 0 + 0k 0 + 0io 0pf + 0w นี่คือ ตัวอย่างที่ดีคือความรู้ทั่วไปผิด
Martin York

36
ในขณะที่การโทรนั้นสำคัญจริงๆนั่นเป็นเพียงผลประโยชน์เล็กน้อยที่คุณได้รับโดยใช้อินไลน์ กำไรหลักคือตอนนี้คอมไพเลอร์ดูว่าพอยน์เตอร์ไม่ได้ใช้นามแฝงซึ่งตัวแปรของผู้ที่โทรเข้ามาอยู่ใน callee และอื่น ๆ ดังนั้นการเพิ่มประสิทธิภาพต่อไปนี้คือสิ่งที่สำคัญกว่า
Johannes Schaub - litb

31
มันอาจไม่สร้างความแตกต่างในตัวอย่างนี้เนื่องจากผลลัพธ์ของฟังก์ชั่นไม่เคยใช้หรือฟังก์ชั่นนี้มีผลข้างเคียง เราเห็นประสิทธิภาพที่วัดได้ในการประมวลผลภาพ
ฐานราก

4
เหตุผลที่ไม่มีความแตกต่างอาจเป็นเพราะคอมไพเลอร์อาจอินไลน์ตามข้อตกลงของตัวเอง; หรือรหัสมีขนาดเล็กจึงไม่มีปัญหาการดึงรหัสล่วงหน้า
einpoklum

3
@einpoklum คอมไพเลอร์อาจปรับให้เหมาะกับลูปทั้งหมดเนื่องจากสิ่งนั้น
noɥʇʎԀʎzɐɹƆ

197

ข้อดี

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

ข้อเสีย

  • มันสามารถทำให้โค้ดของคุณมีขนาดใหญ่ขึ้น (เช่นถ้าคุณใช้อินไลน์สำหรับฟังก์ชั่นที่ไม่สำคัญ) เช่นนี้สามารถกระตุ้นการเพจและเอาชนะการปรับให้เหมาะสมจากคอมไพเลอร์
  • มันทำลายการห่อหุ้มของคุณเล็กน้อยเพราะมันจะเปิดเผยภายในของการประมวลผลวัตถุของคุณ (แต่จากนั้นสมาชิก "ส่วนตัว" ทุกคนก็ต้องการเช่นกัน) ซึ่งหมายความว่าคุณต้องไม่ใช้การอินไลน์ในรูปแบบ PImpl
  • มันแบ่งการห่อหุ้มของคุณเล็กน้อย 2: C ++ อินไลน์ที่ได้รับการแก้ไขในเวลารวบรวม ซึ่งหมายความว่าคุณควรเปลี่ยนรหัสของฟังก์ชั่นอินไลน์คุณจะต้องคอมไพล์รหัสทั้งหมดใหม่อีกครั้งเพื่อให้แน่ใจว่ามันจะได้รับการอัพเดต (ด้วยเหตุผลเดียวกันฉันหลีกเลี่ยงค่าเริ่มต้นสำหรับพารามิเตอร์ฟังก์ชั่น)
  • เมื่อใช้ในส่วนหัวจะทำให้ไฟล์ส่วนหัวของคุณใหญ่ขึ้นและทำให้เจือจางข้อมูลที่น่าสนใจ (เช่นรายการวิธีการเรียน) ด้วยรหัสที่ผู้ใช้ไม่สนใจ (นี่คือเหตุผลที่ฉันประกาศฟังก์ชั่นอินไลน์ภายใน class แต่จะกำหนดไว้ในส่วนหัวหลังจาก body body และไม่เคยอยู่ใน body class)

อินไลน์มายากล

  • คอมไพเลอร์อาจมีหรือไม่มีอินไลน์ฟังก์ชั่นที่คุณทำเครื่องหมายว่าเป็นแบบอินไลน์ มันอาจตัดสินใจที่จะฟังก์ชั่นแบบอินไลน์ไม่ได้ทำเครื่องหมายว่าเป็นแบบอินไลน์ที่รวบรวมหรือเวลาเชื่อมโยง
  • Inline ทำงานเหมือนกับการคัดลอก / วางที่ควบคุมโดยคอมไพเลอร์ซึ่งค่อนข้างแตกต่างจากมาโครตัวประมวลผลล่วงหน้า: มาโครจะถูกบังคับแบบอินไลน์, จะทำให้มลภาวะของเนมสเปซและรหัสทั้งหมดจะไม่สามารถ debuggable ได้ง่ายและทำได้แม้ หากคอมไพเลอร์จะปกครองมันเป็นไร้ประสิทธิภาพ
  • ทุกวิธีของคลาสที่กำหนดไว้ภายในเนื้อหาของคลาสนั้นจะถือว่าเป็น "inlined" (แม้ว่าคอมไพเลอร์ยังสามารถตัดสินใจที่จะไม่อินไลน์ได้
  • วิธีการเสมือนไม่ควรจะ inlinable ถึงกระนั้นบางครั้งเมื่อคอมไพเลอร์สามารถทราบได้อย่างแน่นอนว่าชนิดของวัตถุ (เช่นวัตถุที่ถูกประกาศและสร้างขึ้นภายในร่างกายของฟังก์ชั่นเดียวกัน) แม้กระทั่งฟังก์ชั่นเสมือนจะ inline เพราะคอมไพเลอร์รู้ชนิดของวัตถุ
  • วิธีการ / ฟังก์ชั่นเทมเพลตนั้นไม่ได้ถูกแทรกเสมอ
  • ขั้นตอนต่อไปหลังจาก "inline" คือการทำแผนที่แม่แบบ เช่นโดย "inlining" โค้ดของคุณในเวลารวบรวมบางครั้งคอมไพเลอร์สามารถอนุมานผลลัพธ์สุดท้ายของฟังก์ชั่น ... ดังนั้นอัลกอริทึมที่ซับซ้อนสามารถบางครั้งลดลงเป็นreturn 42 ;คำสั่งชนิด นี่สำหรับฉันอินไลน์อย่างมาก มันเกิดขึ้นน้อยมากในชีวิตจริงทำให้การรวบรวมนานขึ้นจะไม่ขยายโค้ดของคุณ แต่เช่นเดียวกับ grail อย่าพยายามใช้มันทุกที่เพราะการประมวลผลส่วนใหญ่ไม่สามารถแก้ไขได้ด้วยวิธีนี้ ... ถึงกระนั้นก็ยังเจ๋งอยู่ดี ...
    :-p

คุณบอกว่ามันทำลาย encapsulation ของคุณเล็กน้อย คุณช่วยอธิบายด้วยตัวอย่างได้ไหม
Destructor

6
@PravasiMeet: มันคือ C ++ สมมติว่าคุณส่ง DLL / shared library ไปยังไคลเอนต์ที่คอมไพล์แล้ว ฟังก์ชั่นอินไลน์ foo โดยใช้สมาชิกตัวแปร X และทำงาน Y จะได้รับการแทรกในรหัสของลูกค้า สมมติว่าจำเป็นต้องส่ง DLL รุ่นปรับปรุงของคุณที่คุณเปลี่ยนตัวแปรสมาชิกเป็น Z และเพิ่มงาน YY นอกเหนือจากการทำงาน Y ลูกค้าเพียงแค่คัดลอก DLL ลงในโครงการและ BOOM เพราะรหัสของ foo ในไบนารีของพวกเขาไม่ใช่รหัสที่อัปเดตที่คุณเขียน ... แม้ว่าไคลเอนต์จะไม่สามารถเข้าถึงรหัสส่วนตัวของคุณได้ตามกฎหมายอินไลน์ก็ทำให้มันเป็น "สาธารณะ"
paercebal

@ paercebal เกี่ยวกับสัญลักษณ์แสดงหัวข้อย่อยที่สองของคุณคุณสามารถให้ตัวอย่างของเมื่อแม่แบบฟังก์ชั่นไม่ได้อยู่ในบรรทัด? ฉันคิดว่าพวกเขาอินไลน์อยู่เสมอแม้ว่าตอนนี้ฉันจะไม่มีการอ้างอิงที่มีประโยชน์ (การทดสอบอย่างง่ายดูเหมือนว่าจะยืนยันได้)
Konrad Rudolph

@KonradRudolph ใน n4594 3.2/6: There can be more than one definition of [..] inline function with external linkage [..] non-static function templateฉันเห็น: ที่ 5.1.5 / For a generic lambda, the closure type has a public inline function call operator member template6 และใน7.1.2/2: the use of inline keyword is to declare an inline functionกรณีที่มันเป็นข้อเสนอแนะเพื่อ inline ร่างกายฟังก์ชั่น ณ จุดที่โทร ดังนั้นฉันสรุปได้ว่าแม้ว่าพวกเขาจะสามารถทำงานได้เหมือนกันฟังก์ชั่นอินไลน์และแม่แบบฟังก์ชั่นยังคงแยกจากกันความคิดมุมฉากที่สามารถผสม (เช่นแม่แบบฟังก์ชั่นอินไลน์)
paercebal

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

42

ใน archaic C และ C ++ inlineมีลักษณะregisterดังนี้: ข้อเสนอแนะ (ไม่มีอะไรมากไปกว่าข้อเสนอแนะ) สำหรับคอมไพเลอร์เกี่ยวกับการปรับให้เหมาะสมที่สุด

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

inline เป็นสิ่งจำเป็นถ้าฟังก์ชั่น (ไม่ว่าซับซ้อนหรือ "เชิงเส้น") ถูกกำหนดในไฟล์ส่วนหัวเพื่ออนุญาตให้หลายแหล่งรวมมันโดยไม่ได้รับข้อผิดพลาด "หลายคำนิยาม" โดย linker

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

//fileA.h
inline void afunc()
{ std::cout << "this is afunc" << std::endl; }

//file1.cpp
#include "fileA.h"
void acall()
{ afunc(); }

//main.cpp
#include "fileA.h"
void acall();

int main()
{ 
   afunc(); 
   acall();
}

//output
this is afunc
this is afunc

หมายเหตุรวมของ fileA.h เป็นสองไฟล์ .cpp afunc()ผลในสองกรณีของ ตัวเชื่อมโยงจะยกเลิกหนึ่งในนั้น หากไม่inlineได้ระบุไว้ลิงเกอร์จะบ่น


16

Inlining เป็นข้อเสนอแนะสำหรับคอมไพเลอร์ซึ่งมีอิสระที่จะเพิกเฉย มันเหมาะสำหรับรหัสขนาดเล็ก

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

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

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

ฉันมักจะทิ้งการตัดสินใจเหล่านี้ไว้ในคอมไพเลอร์ทุกวันนี้ คนที่เขียนพวกเขามักจะมีความรู้ในรายละเอียดของสถาปัตยกรรมพื้นฐาน


12

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

ข้อดี: -

  1. มันไม่จำเป็นต้องใช้ฟังก์ชั่นการโทรค่าใช้จ่าย

  2. นอกจากนี้ยังประหยัดค่าใช้จ่ายของตัวแปรที่ผลัก / ป๊อปอัพในกองในขณะที่ฟังก์ชั่นการโทร

  3. นอกจากนี้ยังบันทึกค่าใช้จ่ายในการโทรกลับจากฟังก์ชั่น

  4. มันเพิ่มตำแหน่งของการอ้างอิงโดยใช้คำสั่งแคช

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

หากต้องการตรวจสอบเพิ่มเติมเกี่ยวกับมันสามารถติดตามได้ที่ลิงค์นี้ http://tajendrasengar.blogspot.com/2010/03/what-is-inline-function-in-cc.html


4
1) มันเป็นข้อเสนอแนะไม่ใช่คำสั่ง 2) มันอาจทำให้แคชหายไปมากขึ้นเนื่องจากการเพิ่มขนาดรหัสหากฟังก์ชั่นที่ใช้กันทั่วไปมีการ inline มาก
Flexo

3
ลิงก์อยู่ท้ายบล็อกส่วนตัวของคุณหรือไม่ หากเป็นเช่นนั้นคุณควรประกาศให้เป็นเช่นนั้นมิฉะนั้นดูเหมือนว่าเป็นสแปม
เฟล็กโซ

6

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

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


@Johnsyweb: อ่านคำตอบของฉันอย่างระมัดระวัง สิ่งที่คุณพูดเป็นเรื่องจริงเมื่อคุณสร้างปฏิบัติการ แต่คอมไพเลอร์ไม่สามารถเพิกเฉยinlineเมื่อสร้างไลบรารีที่แบ่งใช้!
doc

4

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


คอมไพเลอร์หลายคนจะไม่ทำเช่นนี้ MSVC จะไม่ทำเช่นนี้เว้นแต่คุณจะบอกให้
paulm

4

inlineอนุญาตให้คุณวางนิยามฟังก์ชันในไฟล์ส่วนหัวและ#includeไฟล์ส่วนหัวนั้นในไฟล์ต้นฉบับหลายไฟล์โดยไม่ละเมิดกฎข้อกำหนดเดียว


3

โดยทั่วไปการพูดวันนี้กับคอมไพเลอร์ทันสมัยที่กังวลเกี่ยวกับการฝังสิ่งใด ๆ ที่ค่อนข้างเสียเวลา คอมไพเลอร์ควรเพิ่มประสิทธิภาพการพิจารณาทั้งหมดเหล่านี้ให้คุณจริง ๆ ผ่านการวิเคราะห์โค้ดของตัวเอง ถ้าคุณสนใจความเร็วบอกคอมไพเลอร์เพื่อปรับความเร็ว ถ้าคุณสนใจเรื่องพื้นที่ให้บอกคอมไพเลอร์เพื่อปรับพื้นที่ให้เหมาะสม ในฐานะที่เป็นคำตอบอื่นที่พาดพิงถึงคอมไพเลอร์ที่ดีจะอินไลน์โดยอัตโนมัติหากเหมาะสมจริงๆ

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

เมื่อใดที่จะรวมและ / หรือกำหนดแมโครเพื่อบังคับให้รวม? - เฉพาะเมื่อคุณมีการเพิ่มความเร็วที่พิสูจน์แล้วและจำเป็นสำหรับส่วนสำคัญของรหัสที่ทราบว่ามีผลกระทบต่อประสิทธิภาพโดยรวมของแอปพลิเคชัน


…ถ้าคุณสนใจเรื่องพื้นที่ให้บอกคอมไพเลอร์เพื่อปรับพื้นที่ให้เหมาะสม - การบอกคอมไพเลอร์เพื่อให้ได้ความเร็วที่เหมาะสมอาจส่งผลให้ไบนารีที่เล็กลงด้วย C ++ และ C ในทำนองเดียวกันการบอกคอมไพเลอร์เพื่อปรับพื้นที่ iow คุณสมบัติเหล่านี้ไม่ได้ทำงานตามที่โฆษณาไว้เสมอ มนุษย์มีความสามารถในการเข้าใจบางแง่มุมของโปรแกรมของพวกเขาดีกว่าการตีความโดยทั่วไปของคอมไพเลอร์ การแทรกแซงของมนุษย์ไม่จำเป็นต้องเป็นสิ่งเลวร้าย
justin

3

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


1

ตกอยู่ในปัญหาเดียวกันกับการฝังฟังก์ชั่นเข้าไปในห้องสมุด ดูเหมือนว่าฟังก์ชั่นแบบอินไลน์จะไม่ถูกรวบรวมเข้าไปในห้องสมุด ผลที่ตามมา linker ทำให้เกิดข้อผิดพลาด "การอ้างอิงที่ไม่ได้กำหนด" หากปฏิบัติการต้องการใช้ฟังก์ชั่นอินไลน์ของห้องสมุด (เกิดขึ้นกับฉันรวบรวมแหล่ง Qt กับ gcc 4.5


1

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


1

ศาสตราจารย์ด้านวิทยาการคอมพิวเตอร์ของเรากระตุ้นให้เราไม่ใช้ inline ในโปรแกรม c ++ เมื่อถูกถามว่าทำไมเขาอธิบายให้เราฟังว่าคอมไพเลอร์สมัยใหม่ควรตรวจจับเมื่อใช้อินไลน์โดยอัตโนมัติ

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


5
น่าเสียดายที่ศาสตราจารย์ของคุณผิดอย่างสิ้นเชิง inlineใน C ++ มีความหมายที่แตกต่างกันสองประการ - หนึ่งในนั้นเท่านั้นที่เกี่ยวข้องกับการปรับให้เหมาะสมที่สุดและอาจารย์ของคุณนั้นถูกต้องเกี่ยวกับเรื่องนั้น แต่ความหมายที่สองของinlineมักจะเป็นสิ่งที่จำเป็นเพื่อตอบสนองความกฎข้อหนึ่งนิยาม
Konrad Rudolph

-1

บทสรุปจากการสนทนาอื่นที่นี่:

มีข้อเสียใด ๆ กับฟังก์ชั่นแบบอินไลน์?

เห็นได้ชัดว่าไม่มีอะไรผิดปกติกับการใช้ฟังก์ชั่นอินไลน์

แต่มันก็คุ้มค่าที่จะสังเกตประเด็นต่อไปนี้!

  • การใช้อินไลน์มากเกินไปอาจทำให้โปรแกรมช้าลงได้ ขึ้นอยู่กับขนาดของฟังก์ชั่นการใช้งานแบบอินไลน์อาจทำให้ขนาดรหัสเพิ่มขึ้นหรือลดลงได้ การใช้ฟังก์ชั่น accessor ขนาดเล็กมากมักจะลดขนาดรหัสในขณะที่การใช้ฟังก์ชันขนาดใหญ่มากสามารถเพิ่มขนาดรหัสได้อย่างมาก ในโปรเซสเซอร์ที่ทันสมัยโค้ดขนาดเล็กมักจะทำงานได้เร็วขึ้นเนื่องจากการใช้แคชคำสั่งที่ดีขึ้น - หลักเกณฑ์ของ Google

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

  • มีบางสถานการณ์ที่ฟังก์ชันอินไลน์อาจไม่ทำงาน:

    • สำหรับฟังก์ชันส่งคืนค่า หากมีข้อความสั่งคืน
    • สำหรับฟังก์ชันที่ไม่ส่งคืนค่าใด ๆ ถ้ามีลูปสลับหรือมีคำสั่ง goto อยู่
    • หากฟังก์ชั่นซ้ำ -Source
  • __inlineคำหลักที่ทำให้เกิดการทำงานที่จะ inlined เท่านั้นถ้าคุณระบุตัวเลือกเพิ่มประสิทธิภาพ หากระบุการปรับให้เหมาะสมไม่ว่า__inlineจะให้เกียรติหรือไม่ก็ตามนั้นขึ้นอยู่กับการตั้งค่าของตัวเลือกเครื่องมือเพิ่มประสิทธิภาพแบบอินไลน์ โดยค่าเริ่มต้นตัวเลือกแบบอินไลน์จะมีผลเมื่อใดก็ตามที่มีการเรียกใช้เครื่องมือเพิ่มประสิทธิภาพ หากคุณระบุการปรับให้เหมาะสมคุณต้องระบุตัวเลือก noinline หากคุณต้องการ__inlineให้ละเว้นคำสำคัญ -Source


3
จะเป็นจริงถ้า inline เป็นคำสั่งและไม่ใช่คำใบ้สำหรับคอมไพเลอร์ คอมไพเลอร์ตัดสินใจว่าจะทำอะไรในอินไลน์
Martin York

1
@ LokiAstari ฉันรู้ว่าอินไลน์คือคำขอให้คอมไพเลอร์ อาร์กิวเมนต์ของฉันคือถ้ามันบอกใบ้ให้คอมไพเลอร์เราควรปล่อยให้คอมไพเลอร์ตัดสินใจว่าอะไรดีที่สุด เหตุใดจึงต้องใช้แบบอินไลน์ แต่อย่างใดแม้ว่าคุณจะใช้แบบอินไลน์ก็ยังคงเป็นผู้รวบรวมผู้ที่จะตัดสินใจขั้นสุดท้าย ฉันยังสงสัยว่า Microsoft เปิดตัว _forceinline แล้ว
กฤษณะ Oza

@krish_oza: ความคิดเห็นของฉันที่นี่ เป็นเรื่องเกี่ยวกับคำตอบนี้ คำตอบที่นี่ผิดอย่างสมบูรณ์ เนื่องจากคอมไพเลอร์ไม่สนใจinlineคีย์เวิร์ดสำหรับการพิจารณาว่าอินไลน์โค้ดทุกจุดที่ทำข้างบนนั้นผิดหรือไม่ พวกเขาจะเป็นจริงถ้าคอมไพเลอร์ใช้คำสำคัญสำหรับการทำอินไลน์ (มันจะใช้สำหรับการพิจารณาการทำเครื่องหมายหลายคำจำกัดความสำหรับการเชื่อมโยงวัตถุประสงค์)
Martin York
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.