Փոխանակ պատասխանելու, թե ինչ է դա անում, ես պատասխանում եմ, թե ինչպես անեմ այն, ինչ ուզում եմ: Գոյություն ունեն ներդիրների 5 տեսակ, բոլորը հասանելի են GNU C89-ում, ստանդարտ C99-ում և C++-ում: MSVC-ն ունի դրանցից որոշ (նշեք, որ ես չեմ փորձարկել MSVC կոդը)
always inline, unless the address is taken
Ցանկացած հայտարարության մեջ ավելացրեք __attribute__((always_inline))
, այնուհետև օգտագործեք ստորև բերված դեպքերից մեկը՝ դրա հասցեի ընդունման հնարավորությունը կարգավորելու համար:
Դուք, հավանաբար, երբեք չպետք է օգտագործեք սա, եթե դրա իմաստաբանությունը ձեզ հարկավոր չէ (օրինակ՝ որոշակի ձևով ազդելու ժողովի վրա կամ օգտագործել alloca
): Կոմպիլյատորը սովորաբար ձեզնից լավ գիտի, արդյոք արժե այն:
MSVC-ն ունի __forceinline
, որը հիմնականում նույնն է թվում, բայց, ըստ երևույթին, այն հրաժարվում է ներդնել բավականին սովորական հանգամանքներում (օրինակ, երբ օպտիմիզացումն անջատված է), որտեղ մյուս կոմպիլյատորները լավ են աշխատում:
inline and emit a weak symbol (like C++, aka "just make it work")
__attribute__((weak))
void foo(void);
inline void foo(void) { ... }
Նկատի ունեցեք, որ դա թողնում է նույն կոդի մի փունջ կրկնօրինակներ, և կապողն ընտրում է մեկը կամայականորեն:
MSVC-ն, ըստ երևույթին, չունի ճշգրիտ համարժեք C ռեժիմում, չնայած կան մի քանի նմանատիպ բաներ: Թվում է, թե __declspec(selectany)
-ը խոսում է միայն տվյալների մասին, ուստի մի՞թե չի կիրառվում գործառույթների վրա: Կա նաև կապող աջակցություն թույլ կեղծանունների համար, բայց արդյո՞ք դա աշխատում է այստեղ:
inline, but never emit any symbol (leaving external references)
__attribute__((gnu_inline))
extern inline void foo(void) { ... }
MSVC-ի __declspec(dllimport)
-ը, զուգորդված փաստացի սահմանման հետ (այլապես անսովոր), ենթադրաբար դա անում է:
emit always (for one TU, to resolve the preceding)
Ակնարկվող տարբերակը թույլ նշան է հաղորդում C++-ում, բայց ուժեղ խորհրդանիշ C-ի երկու բարբառներում.
void foo(void);
inline void foo(void) { ... }
Կամ դուք կարող եք դա անել առանց ակնարկի, որն արտահայտում է ուժեղ խորհրդանիշ երկու լեզուներով.
void foo(void) { ... }
Ընդհանրապես, դուք գիտեք, թե ինչ լեզվով է ձեր TU-ն, երբ տալիս եք սահմանումները, և, հավանաբար, շատ գծագրման կարիք չունեք:
MSVC-ի __declspec(dllexport)
-ն ենթադրաբար դա անում է:
inline and emit in every TU
static inline void foo(void) { ... }
Այս բոլորի համար, բացի static
-ից, կարող եք վերևում ավելացնել void foo(void)
հայտարարություն: Սա օգնում է մաքուր վերնագրեր գրելու լավագույն պրակտիկային, այնուհետև #include
առանձին ֆայլ ստեղծելու ներկառուցված սահմանումներով: Այնուհետև, եթե օգտագործում եք C ոճի ներդիրներ, #define
որոշ մակրո տարբեր կերպ մեկ հատուկ TU-ում՝ տրամադրելու գծից դուրս սահմանումներ:
Մի մոռացեք extern "C"
-ը, եթե վերնագիրը կարող է օգտագործվել ինչպես C-ից, այնպես էլ C++-ից:
Կան նաև մի քանի հարակից բաներ.
never inline
Ֆունկցիայի ցանկացած հայտարարությանն ավելացրեք __attribute__((noinline))
:
MSVC-ն ունի __declspec(noinline)
, բայց այն փաստաթղթավորված է, որ աշխատում է միայն անդամի գործառույթների համար: Այնուամենայնիվ, ես տեսել եմ անվտանգության հատկանիշների հիշատակում, որոնք կարող են կանխել ներդիրումը:
force other functions to be inlined into this one if possible.
Ավելացնել __attribute__((flatten))
ֆունկցիայի ցանկացած հայտարարության:
Նկատի ունեցեք, որ noinline
-ն ավելի հզոր է, քան սա, ինչպես նաև գործառույթները, որոնց սահմանումը հայտնի չէ կոմպիլյացիայի ժամանակ:
MSVC-ն, ըստ երևույթին, չունի համարժեք: Ես տեսել եմ [[msvc::forceinline_calls]]
-ի մեկ հիշատակում (կիրառվել է հայտարարության կամ արգելափակման համար), բայց դա ռեկուրսիվ չէ:
08.07.2018
extern inline
-ը ենթակա է մեկ սահմանման կանոնին, և սա է սահմանումը: Բայց եթե իրականացման կողմից սահմանված օպտիմալացման էվրիստիկաները հետևում ենinline
հիմնաբառը որպես առաջարկություն, որ գործառույթի զանգերը հնարավորինս արագ լինեն (ISO 9899:1999 §6.7.4 (5),extern inline
հաշվում 11.05.2017__attribute__((always_inline))
է: Այն ստիպում է ֆունկցիան ներգծվել, նույնիսկ եթե օպտիմալացումներն անջատված են: Այն օգտակար է չափազանց կարճ գործառույթների համար, որոնք կոչվում են չափազանց հաճախ, օրինակ, վեկտորային մաթեմատիկական գրադարաններում, որոնք թույլ են տալիս վրիպազերծումը դանդաղեցնել, երբ օպտիմիզացիան անջատված է, եթե դրանք ներգծված չեն: 18.10.2017inline
(ոչstatic inline
) ֆունկցիա, ինչպես C99inline
-ում, այն տարբերությամբ, որ C++-ում ոչ մի աղբյուր (.cxx
) ֆայլ դրա համար հայտարարագիր չի ունենա (in C99, ճիշտ մեկ աղբյուր (.c
) ֆայլ պետք է նախատիպին տրամադրիextern inline
, որը կունենա միակ և միակ սահմանումը համապատասխան օբյեկտի.o
ֆայլում): Ճիշտ? 03.07.2021