2016-06-26 3 views
56

2016 ओलु आईएसओ सी ++ मानक बैठक में, Inline Variables नामक एक प्रस्ताव मानक समिति द्वारा सी ++ 17 में मतदान किया गया था।इनलाइन चर कैसे काम करते हैं?

आम आदमी के शब्दों में, इनलाइन चर क्या हैं, वे कैसे काम करते हैं और वे किसके लिए उपयोगी हैं? इनलाइन चर को कैसे घोषित किया जाना चाहिए, परिभाषित और उपयोग किया जाना चाहिए?

+0

@jotik मुझे लगता है कि बराबर आपरेशन अपने मूल्य द्वारा चर के किसी भी घटना की जगह किया जाएगा। आम तौर पर यह केवल तभी मान्य होता है जब चर 'const' है। – melpomene

+3

यह एकमात्र चीज नहीं है कि 'इनलाइन' कीवर्ड कार्यों के लिए करता है। 'इनलाइन' कीवर्ड, जब फ़ंक्शंस पर लागू होता है, का एक अन्य महत्वपूर्ण प्रभाव होता है, जो सीधे चर के लिए अनुवाद करता है। एक हेडलाइन फ़ाइल में संभावित रूप से घोषित एक 'इनलाइन' फ़ंक्शन, लिंक समय पर "डुप्लिकेट प्रतीक" त्रुटियों का नतीजा नहीं होगा, भले ही हेडर को कई अनुवाद इकाइयों द्वारा '# शामिल किया गया हो। परिवर्तनीय पर लागू होने पर 'इनलाइन' कीवर्ड, का सटीक परिणाम होगा। समाप्त। –

+2

^'इस कोड में किसी भी कॉल को अपने कोड की एक इन-प्लेस कॉपी के साथ प्रतिस्थापित करें' के अर्थ में, 'इनलाइन' केवल एक कमजोर, ऑप्टिमाइज़र के लिए बाध्यकारी अनुरोध है। कंपाइलर अनुरोधित फ़ंक्शंस इनलाइन फ़ंक्शंस और/या उन लोगों को इनलाइन करने के लिए स्वतंत्र नहीं हैं जिन्हें आपने एनोटेट नहीं किया था। इसके बजाय, 'इनलाइन' कीवर्ड का वास्तविक उद्देश्य कई परिभाषा त्रुटियों को बाधित करना है। –

उत्तर

60

प्रस्ताव के पहले वाक्य:

inline विनिर्देशक चर के रूप में अच्छी तरह के रूप में कार्य करने के लिए लागू किया जा सकता।

inline की ¹guaranteed प्रभाव के रूप में एक समारोह के लिए आवेदन किया, समारोह हूबहू बाहरी लिंकेज के साथ परिभाषित किया जाना,, कई अनुवाद इकाइयों में अनुमति है। इन-प्रैक्टिस के लिए जिसका अर्थ हेडर में फ़ंक्शन को परिभाषित करना है, जिसे एकाधिक अनुवाद इकाइयों में शामिल किया जा सकता है। प्रस्ताव इस संभावना को चर के लिए बढ़ाता है।

तो, व्यावहारिक दृष्टि से (अब स्वीकार किए जाते हैं) प्रस्ताव आप एक हेडर फाइल में, एक बाहरी लिंकेज const नाम स्थान गुंजाइश चर, या किसी भी static वर्ग डेटा सदस्य को परिभाषित करने के inline कीवर्ड का उपयोग करने की अनुमति देता है ताकि कई परिभाषाएं कि नतीजा जब उस शीर्षलेख को कई अनुवाद इकाइयों में शामिल किया गया है तो लिंकर – के साथ ठीक है, यह सिर्फ एक चुनता है।

कक्षा टेम्पलेट्स में static चर का समर्थन करने के लिए सी ++ 14 तक आंतरिक मशीनरी वहां तक ​​पहुंच गई है, लेकिन उस मशीनरी का उपयोग करने का कोई सुविधाजनक तरीका नहीं था। एक तरह

template< class Dummy > 
struct Kath_ 
{ 
    static std::string const hi; 
}; 

template< class Dummy > 
std::string const Kath_<Dummy>::hi = "Zzzzz..."; 

using Kath = Kath_<void>; // Allows you to write `Kath::hi`. 

चाल का सहारा लेना से सी ++ 17 था और उसके बाद मेरा मानना ​​है कि एक बस

struct Kath 
{ 
    static std::string const hi; 
}; 

inline std::string const Kath::hi = "Zzzzz..."; // Simpler! 

है & hellip लिख सकते हैं; एक हेडर फ़ाइल में।

प्रस्ताव शब्दों

एक इनलाइन स्थिर डेटा सदस्य वर्ग परिभाषा में परिभाषित किया जा सकता है और एक ब्रेस या बराबर-प्रारंभकर्ता pecify सकता है। यदि सदस्य को constexpr विनिर्देशक के साथ घोषित किया गया है, तो इसे नामस्थान स्कोप में पुन: प्रारंभ किया जा सकता है जिसमें कोई प्रारंभकर्ता नहीं है (यह उपयोग बहिष्कृत है; डीएक्स देखें)। अन्य स्थैतिक डेटा सदस्यों की घोषणाओं में ब्रेस-या-बराबर-इन इटाइलाइज़र

और नरकिप निर्दिष्ट नहीं करेगा; जो उपर्युक्त को

struct Kath 
{ 
    static inline std::string const hi = "Zzzzz..."; // Simplest! 
}; 

और नरकिप को और अधिक सरल बनाने की अनुमति देता है; जैसा कि उत्तर में a comment में टी.सी. द्वारा उल्लेख किया गया है।

इसके अलावा, ​constexpr विनिर्देशक स्थिर डेटा सदस्यों के साथ-साथ कार्यों के लिए inline का तात्पर्य है।


नोट्स:
¹ एक समारोह inline के लिए भी अनुकूलन के बारे में एक हिंट प्रभाव पड़ता है, कि संकलक समारोह की मशीन कोड के प्रत्यक्ष प्रतिस्थापन के साथ इस समारोह की कॉल को बदलने के लिए पसंद करते हैं चाहिए। इस संकेत को अनदेखा किया जा सकता है।

+2

इसके अलावा, कॉन्स्ट प्रतिबंध केवल नामस्थान स्कोप चर पर लागू होता है। कक्षा-स्कोप वाले (जैसे 'कथ :: हाय') को स्थिर नहीं होना चाहिए। –

+0

@TC: ओह, "एक इनलाइन स्थैतिक डेटा सदस्य को कक्षा परिभाषा में परिभाषित किया जा सकता है और एक ब्रेस-या-बराबर-प्रारंभकर्ता निर्दिष्ट कर सकता है। यदि सदस्य को कॉन्स्टेक्स विनिर्देशक के साथ घोषित किया गया है, तो यह नामस्थान में पुन: घोषित हो सकता है कोई प्रारंभकर्ता के साथ गुंजाइश (यह उपयोग बहिष्कृत है; डीएक्स देखें)। अन्य स्थिर डेटा सदस्यों की घोषणा एक braceorequalinitializer निर्दिष्ट नहीं करेगा "। –

+3

[नई रिपोर्ट] (https: //botondballo.wordpress।कॉम/2016/07/06/यात्रा-रिपोर्ट-सी-मानकों-बैठक-इन-औल्लू-जून-2016 /) इंगित करता है कि 'कॉन्स्ट' प्रतिबंध पूरी तरह से गिरा दिया गया है। –

3

इनलाइन चर इनलाइन फ़ंक्शंस के समान ही हैं। यह लिंकर को संकेत देता है कि चर के केवल एक उदाहरण मौजूद होना चाहिए, भले ही चर कई संकलन इकाइयों में देखा जाए। लिंकर को यह सुनिश्चित करने की आवश्यकता है कि कोई और प्रतियां नहीं बनाई जाएंगी।

इनलाइन चर का उपयोग हेडर केवल पुस्तकालयों में ग्लोबल्स को परिभाषित करने के लिए किया जा सकता है। सी ++ 17 से पहले, उन्हें वर्कअराउंड (इनलाइन फ़ंक्शंस या टेम्पलेट हैक्स) का उपयोग करना पड़ा।

उदाहरण के लिए, एक वैकल्पिक हल एक इनलाइन समारोह के साथ मेयर की सिंगलटन उपयोग करने के लिए है:

inline T& instance() 
{ 
    static T global; 
    return global; 
} 

वहाँ ज्यादातर प्रदर्शन के संदर्भ में, इस दृष्टिकोण के साथ कुछ कमियां हैं। इस ओवरहेड को टेम्पलेट समाधान से बचा जा सकता है, लेकिन उन्हें गलत करना आसान है।

इनलाइन वैरिएबल की मदद से

, आप सीधे यह घोषणा कर सकते हैं (एक बहु परिभाषा लिंकर त्रुटि मिल रही बिना):

inline T global; 
हैडर से

अलावा केवल पुस्तकालयों, वहाँ अन्य मामलों में जहां इनलाइन चर कर सकते हैं। निर फ्राइडमैन इस विषय को सीपीपीकॉन में अपनी बातचीत में शामिल करते हैं: What C++ developers should know about globals (and the linker)। इनलाइन चर और वर्कअराउंड starts at 18m9s के बारे में हिस्सा।

लंबी कहानी छोटी, यदि आपको संकलन इकाइयों के बीच साझा किए गए वैश्विक चर घोषित करने की आवश्यकता है, तो उन्हें हेडर फ़ाइल में इनलाइन चर के रूप में घोषित करना सीधा है और पूर्व-सी ++ 17 वर्कअराउंड के साथ समस्याओं से बचाता है।

(वहाँ अभी भी मेयर की सिंगलटन के लिए मामलों का उपयोग कर रहे हैं, उदाहरण के लिए यदि आप स्पष्ट रूप आलसी प्रारंभ करना चाहते हैं।)

संबंधित मुद्दे