जवाबों:
प्रीप्रोसेसर मैक्रोज़ आपके कोड पर लागू होने वाले प्रतिस्थापन पैटर्न हैं। उन्हें आपके कोड में लगभग कहीं भी उपयोग किया जा सकता है क्योंकि किसी भी संकलन के शुरू होने से पहले उन्हें उनके विस्तार के साथ बदल दिया जाता है।
इनलाइन फ़ंक्शन वास्तविक फ़ंक्शन हैं जिनके शरीर को सीधे उनकी कॉल साइट में इंजेक्ट किया जाता है। उनका उपयोग केवल वहां किया जा सकता है जहां फ़ंक्शन कॉल उपयुक्त है।
अब, जहाँ तक फ़ंक्शन-जैसे संदर्भ में मैक्रोज़ बनाम इनलाइन फ़ंक्शंस का उपयोग करने की सलाह दी जाती है:
सबसे पहले, प्रीप्रोसेसर मैक्रोज़ संकलन से पहले कोड में "कॉपी पेस्ट" हैं। तो कोई प्रकार की जाँच नहीं है , और कुछ दुष्प्रभाव दिखाई दे सकते हैं
उदाहरण के लिए, यदि आप 2 मानों की तुलना करना चाहते हैं:
#define max(a,b) ((a<b)?b:a)
साइड इफेक्ट दिखाई देते हैं यदि आप max(a++,b++)
उदाहरण के लिए उपयोग करते हैं ( a
या b
दो बार वृद्धि की जाएगी)। इसके बजाय, उपयोग करें (उदाहरण के लिए)
inline int max( int a, int b) { return ((a<b)?b:a); }
max(fibonacci(100), factorial(10000))
कि बड़े को दो बार गणना की जाएगी :(
इनलाइन फ़ंक्शन को कंपाइलर द्वारा विस्तारित किया जाता है, जहां मैक्रोज़ प्रीप्रोसेसर द्वारा विस्तारित होते हैं, जो कि केवल पाठीय प्रतिस्थापन है। हेंस
मैक्रो इनवोकेशन के दौरान कोई प्रकार की जाँच नहीं है, जबकि फ़ंक्शन कॉल के दौरान टाइप जाँच की जाती है।
तर्कों के पुनर्मूल्यांकन और संचालन के क्रम के कारण वृहद विस्तार के दौरान अवांछित परिणाम और अक्षमता हो सकती है। उदाहरण के लिए
#define MAX(a,b) ((a)>(b) ? (a) : (b))
int i = 5, j = MAX(i++, 0);
में परिणाम होगा
int i = 5, j = ((i++)>(0) ? (i++) : (0));
स्थूल विस्तार से पहले स्थूल तर्कों का मूल्यांकन नहीं किया जाता है
#define MUL(a, b) a*b
int main()
{
// The macro is expended as 2 + 3 * 3 + 5, not as 5*8
printf("%d", MUL(2+3, 3+5));
return 0;
}
// Output: 16`
फ़ंक्शन के मामले में मान वापस करने के लिए मैक्रो में रिटर्न कीवर्ड का उपयोग नहीं किया जा सकता है।
इनलाइन कार्यों को ओवरलोड किया जा सकता है
मैक्रों को दिए गए टोकन को ऑपरेटर ## का उपयोग करके सुधारा जा सकता है जिसे टोकन-पेस्टिंग ऑपरेटर कहा जाता है।
मैक्रोज़ आमतौर पर कोड के पुन: उपयोग के लिए उपयोग किया जाता है जहां फ़ंक्शन कॉल के दौरान इनलाइन फ़ंक्शन (अतिरिक्त समय) को समाप्त करने के लिए इनलाइन फ़ंक्शन का उपयोग किया जाता है (एक सबरूटीन पर कूदने से बचना)।
मुख्य अंतर प्रकार की जाँच है। कंपाइलर यह जांच करेगा कि आप इनपुट मानों के रूप में क्या पास करते हैं, यह उस प्रकार का है जिसे फ़ंक्शन में पास किया जा सकता है। प्रीप्रोसेसर मैक्रोज़ के साथ यह सच नहीं है - वे किसी भी प्रकार की जाँच से पहले विस्तारित होते हैं और इससे बग का पता लगाने में गंभीर और मुश्किल हो सकती है।
यहाँ कई अन्य कम स्पष्ट बिंदु उल्लिखित हैं।
पहले से दिए गए लोगों के लिए एक और अंतर जोड़ने के लिए: आप #define
डीबगर में एक के माध्यम से कदम नहीं रख सकते हैं , लेकिन आप इनलाइन फ़ंक्शन के माध्यम से कदम रख सकते हैं।
मैक्रों नामस्थानों की अनदेखी कर रहे हैं। और यही उनकी बुराई करता है।
इनलाइन फ़ंक्शन मैक्रोज़ के समान हैं (क्योंकि संकलन समय पर कॉल के बिंदु पर फ़ंक्शन कोड का विस्तार होता है), इनलाइन फ़ंक्शन कंपाइलर द्वारा पार्स किए जाते हैं, जबकि मैक्रोज़ प्रीप्रोसेसर द्वारा विस्तारित होते हैं। परिणामस्वरूप, कई महत्वपूर्ण अंतर हैं:
कुछ मामलों में, मैक्रोज़ के तर्क के रूप में पारित किए गए अभिव्यक्तियों का एक से अधिक बार मूल्यांकन किया जा सकता है। http://msdn.microsoft.com/en-us/library/bf6bf4cf.aspx
मैक्रो पूर्व-संकलित समय पर विस्तारित होते हैं, आप उन्हें डीबगिंग के लिए उपयोग नहीं कर सकते हैं, लेकिन आप इनलाइन फ़ंक्शन का उपयोग कर सकते हैं।
- अच्छा लेख : http://www.codeguru.com/forum/showpost.php?p=1093923&postcount=1
;
एक इनलाइन फ़ंक्शन वैल्यू सिमेंटिक्स बनाए रखेगा, जबकि एक प्रीप्रोसेसर मैक्रो सिंटैक्स को कॉपी करता है। यदि आप कई बार तर्क का उपयोग करते हैं, तो आप प्रीप्रोसेसर मैक्रो के साथ बहुत सूक्ष्म कीड़े प्राप्त कर सकते हैं - उदाहरण के लिए यदि तर्क में "i ++" जैसे उत्परिवर्तन होता है, जो दो बार निष्पादित होता है तो काफी आश्चर्य होता है। इनलाइन फ़ंक्शन से यह समस्या नहीं होगी।
एक इनलाइन फंक्शनल्यूशन एक सामान्य फ़ंक्शन की तरह ही वाक्यात्मक रूप से व्यवहार करता है, यह प्रकार की सुरक्षा और फ़ंक्शन स्थानीय चर के लिए एक गुंजाइश प्रदान करता है और अगर यह एक तरीका है तो क्लास-सदस्यों तक पहुंच प्रदान करता है। इनलाइन विधियों को कॉल करते समय भी आपको निजी / संरक्षित प्रतिबंधों का पालन करना चाहिए।
मैक्रो और इनलाइन फ़ंक्शन के बीच अंतर जानने के लिए , सबसे पहले हमें यह जानना चाहिए कि वे वास्तव में क्या हैं और हमें उनका उपयोग कब करना चाहिए।
समारोह :
int Square(int x){
return(x*X);
}
int main()
{
int value = 5;
int result = Square(value);
cout << result << endl;
}
फंक्शन कॉल्स में इसके साथ ओवरहेड जुड़ा होता है, क्योंकि फंक्शन खत्म होने के बाद इसे पता करना होता है कि इसे कहां लौटना है और स्टैक मेमोरी में वैल्यू स्टोर करने की भी जरूरत है।
छोटे अनुप्रयोगों के लिए यह एक समस्या नहीं होगी, लेकिन चलो उन वित्तीय अनुप्रयोगों का एक उदाहरण लेते हैं जहां हर सेकंड हजारों लेनदेन हो रहे हैं, हम फ़ंक्शन कॉल के साथ नहीं जा सकते हैं।
मैक्रो:
# define Square(x) x*x;
int main()
{
int value = 5;
int result = Square(value);
cout << result << endl;
}
int परिणाम = वर्ग (x * x)
लेकिन मैक्रोज़ के पास इससे जुड़े कीड़े हैं।
#define Square(x) x*x
int main() {
int val = 5;
int result = Square(val + 1);
cout << result << endl;
return 0;
}
यहां आउटपुट 11 नहीं 36 है ।
ऑनलाइन समारोह :
inline int Square(int x) {
return x * x;
}
int main() {
using namespace std;
int val = 5;
int result = Square(val + 1);
cout << result << endl;
return 0;
}
आउटपुट 36
इनलाइन कीवर्ड फ़ंक्शन को फ़ंक्शन के शरीर के साथ फ़ंक्शन कॉल को बदलने के लिए कंपाइलर का अनुरोध करता है, यहां आउटपुट सही है क्योंकि यह पहले अभिव्यक्ति का मूल्यांकन करता है और फिर पारित हो जाता है। यह फ़ंक्शन कॉल को ओवरहेड को कम कर देता है क्योंकि रिटर्न एड्रेस और स्टैक को स्टोर करने की कोई आवश्यकता नहीं है। फ़ंक्शन तर्कों के लिए मेमोरी की आवश्यकता नहीं है।
मैक्रोज़ और इनलाइन कार्यों के बीच तुलना:
निष्कर्ष:
इनलाइन फ़ंक्शन कभी-कभी मैक्रोज़ की तुलना में अधिक उपयोगी होते हैं, क्योंकि यह प्रदर्शन में सुधार करता है और उपयोग करने के लिए सुरक्षित है और फ़ंक्शन कॉल को भी कम कर देता है। यह संकलक से केवल एक अनुरोध है, कुछ कार्यों को इनलाइन नहीं किया जाएगा:
जो एक अच्छी बात है, क्योंकि जब भी कंपाइलर सोचता है कि चीजों को दूसरे तरीके से करना सबसे अच्छा है।
जीसीसी में (मुझे दूसरों के बारे में निश्चित नहीं है), एक फ़ंक्शन इनलाइन की घोषणा करना, संकलक के लिए एक संकेत है। यह अभी भी दिन के अंत में कंपाइलर पर निर्भर करता है कि वह यह तय करे कि जब भी इसे कहा जाए, तो यह फंक्शन की बॉडी में शामिल है या नहीं।
इन-लाइन फ़ंक्शंस और प्रीप्रोसेसर मैक्रोज़ के बीच का अंतर अपेक्षाकृत बड़ा है। प्रीप्रोसेसर मैक्रोज़ दिन के अंत में सिर्फ टेक्स्ट रिप्लेसमेंट हैं। आप कंपाइलर के लिए तर्कों और रिटर्न प्रकार पर जाँच की जाँच करने की बहुत अधिक क्षमता छोड़ देते हैं। तर्कों का मूल्यांकन बहुत अलग है (यदि आप जिन अभिव्यक्तियों को फ़ंक्शन में पास करते हैं, उनके साइड-इफेक्ट्स हैं, तो आपके पास बहुत ही मजेदार समय डिबगिंग होगा)। जहां फ़ंक्शन और मैक्रोज़ का उपयोग किया जा सकता है, उसके बारे में सूक्ष्म अंतर हैं। उदाहरण के लिए अगर मेरे पास था:
#define MACRO_FUNC(X) ...
जहां MACRO_FUNC स्पष्ट रूप से फ़ंक्शन के शरीर को परिभाषित करता है। विशेष देखभाल की आवश्यकता है ताकि यह सही ढंग से चलता रहे सभी मामलों में एक फ़ंक्शन का उपयोग किया जा सकता है, उदाहरण के लिए एक खराब लिखित MACRO_FUNC एक त्रुटि का कारण होगा
if(MACRO_FUNC(y)) {
...body
}
एक सामान्य फ़ंक्शन का उपयोग वहां किसी समस्या के साथ नहीं किया जा सकता है।
कोडिंग के दृष्टिकोण से, एक इनलाइन फ़ंक्शन एक फ़ंक्शन की तरह है। इस प्रकार, एक इनलाइन फ़ंक्शन और मैक्रो के बीच अंतर एक फ़ंक्शन और मैक्रो के बीच अंतर के समान है।
संकलन के दृष्टिकोण से, एक इनलाइन फ़ंक्शन एक मैक्रो के समान है। इसे सीधे कोड में इंजेक्ट किया जाता है, जिसे कॉल नहीं किया जाता है।
सामान्य तौर पर, आपको इनलाइन फ़ंक्शंस पर विचार करना चाहिए, जिसमें कुछ छोटे ऑप्टिमाइज़ेशन के साथ नियमित फ़ंक्शंस शामिल हैं। और अधिकांश ऑप्टिमाइज़ेशन की तरह, यह कंपाइलर पर निर्भर करता है कि वह यह तय करे कि क्या वास्तव में इसे लागू करना है। अक्सर कंपाइलर विभिन्न कारणों से प्रोग्रामर को इनलाइन करने के किसी भी प्रयास को खुशी से अनदेखा कर देगा।
इनलाइन फ़ंक्शन एक फ़ंक्शन कॉल के रूप में व्यवहार करेंगे यदि इसमें कोई पुनरावृत्ति या पुनरावर्ती कथन मौजूद है, ताकि निर्देशों के बार-बार निष्पादन को रोका जा सके। यह आपके प्रोग्राम की समग्र मेमोरी को बचाने में काफी मददगार है।
#include<iostream>
using namespace std;
#define NUMBER 10 //macros are preprocessed while functions are not.
int number()
{
return 10;
}
/*In macros, no type checking(incompatible operand, etc.) is done and thus use of micros can lead to errors/side-effects in some cases.
However, this is not the case with functions.
Also, macros do not check for compilation error (if any). Consider:- */
#define CUBE(b) b*b*b
int cube(int a)
{
return a*a*a;
}
int main()
{
cout<<NUMBER<<endl<<number()<<endl;
cout<<CUBE(1+3); //Unexpected output 10
cout<<endl<<cube(1+3);// As expected 64
return 0;
}
मैक्रो आमतौर पर फ़ंक्शंस से अधिक तेज़ होते हैं क्योंकि उनमें वास्तविक फ़ंक्शन कॉल ओवरहेड शामिल नहीं होता है।
मैक्रोज़ के कुछ नुकसान: कोई प्रकार की जाँच नहीं है। डीबग करने के लिए पर्याप्त है क्योंकि वे सरल प्रतिस्थापन का कारण बनते हैं। मैक्रो में नाम स्थान नहीं है, इसलिए कोड के एक खंड में एक मैक्रो अन्य अनुभाग को प्रभावित कर सकता है। क्यूआरबीई () उदाहरण के ऊपर मैक्रोज़ साइड इफेक्ट्स का कारण बन सकते हैं।
मैक्रोस आमतौर पर एक लाइनर होते हैं। हालांकि, वे एक से अधिक लाइन शामिल कर सकते हैं। इस तरह के कार्यों में कोई बाधा नहीं है।
#define TWO_N(n) 2 << n
और फिर कितना मज़ा आता है cout << CUBE(TWO_N(3 + 1)) << endl;
? (इसके साथ endl
उन्हें शुरू करने की तुलना में आउटपुट की लाइनों को समाप्त करना बेहतर है ।)