ठीक है, मैं मूल रूप से समझता हूं कि पॉइंटर्स का उपयोग कैसे किया जाए, लेकिन बेहतर प्रोग्रामिंग करने के लिए उनका उपयोग करना सबसे अच्छा नहीं है।
संकेत के उपयोग को शामिल करने के लिए अच्छी परियोजनाएं या समस्याएं क्या हैं ताकि मैं उन्हें बेहतर समझ सकूं?
ठीक है, मैं मूल रूप से समझता हूं कि पॉइंटर्स का उपयोग कैसे किया जाए, लेकिन बेहतर प्रोग्रामिंग करने के लिए उनका उपयोग करना सबसे अच्छा नहीं है।
संकेत के उपयोग को शामिल करने के लिए अच्छी परियोजनाएं या समस्याएं क्या हैं ताकि मैं उन्हें बेहतर समझ सकूं?
जवाबों:
मेमोरी में बड़ी मात्रा में डेटा को मैनिप्युलेट करना जहां पॉइंटर्स वास्तव में चमकते हैं।
एक बड़ी वस्तु को संदर्भ से गुजारना समतल पुरानी संख्या के साथ गुजरने के बराबर है। आप किसी ऑब्जेक्ट की प्रतिलिपि बनाने के विपरीत आवश्यक भागों को सीधे जोड़ सकते हैं, इसे बदल सकते हैं, फिर मूल के स्थान पर कॉपी को वापस रख सकते हैं।
सूचक अवधारणा आपको डेटा के भंडारण को दोहराए बिना पते द्वारा डेटा को संदर्भित करने की अनुमति देती है। यह दृष्टिकोण कुशल एल्गोरिदम लिखने की अनुमति देता है जैसे:
सॉर्टिंग
जब सॉर्ट एल्गोरिथ्म में डेटा ले जाता है, तो आप डेटा के बजाय पॉइंटर को स्थानांतरित कर सकते हैं - 100 चार्ट की एक स्ट्रिंग पर लाखों पंक्तियों को सॉर्ट करने के बारे में सोचें; आप अनावश्यक डेटा आंदोलनों को बहुत सहेजते हैं।
लिंक की गई सूची
आप अगले और / या पिछले आइटम स्थान को संग्रहीत कर सकते हैं न कि रिकॉर्ड से जुड़े संपूर्ण डेटा को।
पासिंग पैरामीटर
इस मामले में, आप डेटा के बजाय डेटा का पता ही पास करते हैं। फिर से, एक नाम संपीड़न एल्गोरिथ्म के बारे में सोचें जो लाखों पंक्तियों पर चलता है।
अवधारणा को डेटा संरचनाओं जैसे कि रिलेशनल डेटाबेस में बढ़ाया जा सकता है जहां एक सूचक एक विदेशी कुंजी के समान है । कुछ भाषा संकेत के उपयोग को प्रोत्साहित नहीं करती हैं जैसे C # और COBOL।
उदाहरण कई स्थानों पर पाए जा सकते हैं जैसे:
निम्नलिखित पोस्ट किसी तरह से प्रासंगिक हो सकती है:
मुझे आश्चर्य है कि किसी अन्य उत्तर ने इसका उल्लेख नहीं किया है: संकेत आपको गैर-सन्निहित और गैर-रैखिक डेटा संरचनाएं बनाने की अनुमति देते हैं, जिसमें एक तत्व जटिल तरीकों से कई अन्य लोगों से संबंधित हो सकता है।
लिंक्ड लिस्ट (एकवचन, दोगुना और गोलाकार रूप से जुड़ा हुआ), पेड़ (लाल-काला, एवीएल, ट्राइ, बाइनरी, स्पेस पार्टिशनिंग…), और ग्राफ सभी संरचनाओं के उदाहरण हैं जिन्हें केवल मूल्यों के बजाय संदर्भ के संदर्भ में सबसे स्वाभाविक रूप से निर्मित किया जा सकता है। ।
एक सरल तरीका बहुरूपता में है। बहुरूपता केवल संकेत के साथ काम करता है।
इसके अलावा, आप किसी भी समय डायनेमिक मेमोरी आवंटन के लिए पॉइंटर्स का उपयोग करते हैं। सी में, यह आमतौर पर तब होता है जब आपको डेटा को किसी सरणी में संग्रहीत करने की आवश्यकता होती है लेकिन आप संकलन समय पर आकार नहीं जानते हैं। फिर आप मैलोॉक को मेमोरी और एक पॉइंटर को एक्सेस करने के लिए आवंटित करेंगे। इसके अलावा, आप इसे जानते हैं या नहीं, जब आप एक सरणी का उपयोग करते हैं तो आप पॉइंटर्स का उपयोग कर रहे हैं।
for(int i = 0; i < size; i++)
std::cout << array[i];
के बराबर है
for(int i = 0; i < size; i++)
std::cout << *(array + i);
यह ज्ञान आपको वास्तव में शांत चीजों को करने की अनुमति देता है जैसे एक पंक्ति में संपूर्ण सरणी की प्रतिलिपि बनाएँ:
while( (*array1++ = *array2++) != '\0')
C ++ में, आप किसी ऑब्जेक्ट के लिए मेमोरी आवंटित करने और पॉइंटर में स्टोर करने के लिए नए का उपयोग करते हैं। आप कभी भी ऐसा करते हैं जब आपको संकलित समय के बजाय रन-टाइम के दौरान ऑब्जेक्ट बनाने की आवश्यकता होती है (यानी कोई विधि एक नई ऑब्जेक्ट बनाता है और इसे एक सूची में संग्रहीत करता है)।
संकेत को बेहतर ढंग से समझने के लिए:
कुछ प्रोजेक्ट खोजें जो विरासत का उपयोग करते हैं।
यहाँ परियोजना है कि मैं अपने दाँत काट रहा हूँ:
एक फ़ाइल से दो nxn मैट्रिसेस में पढ़ें और उन पर बुनियादी वेक्टर अंतरिक्ष संचालन करें और स्क्रीन पर उनका परिणाम प्रिंट करें।
ऐसा करने के लिए, आपको डायनेमिक सरणियों का उपयोग करना होगा और पॉइंटर्स द्वारा अपने ऐरे को संदर्भित करना होगा क्योंकि आपके पास एरेज़ के दो एरे (बहु-आयामी गतिशील एरे) होंगे। आपके द्वारा उस प्रोजेक्ट को पूरा करने के बाद, आपके पास एक अच्छा विचार होगा कि पॉइंटर्स का उपयोग कैसे किया जाए।
वास्तव में यह समझने के लिए कि पॉइंटर्स क्यों महत्वपूर्ण हैं आपको ढेर आवंटन और स्टैक आवंटन के बीच अंतर को समझने की आवश्यकता है।
निम्नलिखित स्टैक आवंटन का एक उदाहरण है:
struct Foo {
int bar, baz
};
void foo(void) {
struct Foo f;
}
स्टैक पर आवंटित वस्तुएं केवल वर्तमान फ़ंक्शन निष्पादन की अवधि के लिए मौजूद हैं। जब कॉल foo
स्कोप से बाहर जाता है तो वैरिएबल करता है f
।
एक मामला जहां यह एक मुद्दा बन जाता है, जब आपको एक फ़ंक्शन से एक अभिन्न प्रकार के अलावा कुछ और वापस करने की आवश्यकता होती है (उदाहरण के लिए ऊपर के उदाहरण से फू संरचना)।
उदाहरण के लिए, निम्न फ़ंक्शन तथाकथित "अपरिभाषित व्यवहार" होगा।
struct Foo {
int bar, baz
};
struct Foo *foo(void) {
struct Foo f;
return &f;
}
यदि आप struct Foo *
किसी फ़ंक्शन से कुछ वापस करना चाहते हैं , तो आपको वास्तव में एक ढेर आवंटन की आवश्यकता है:
struct Foo {
int bar, baz
};
struct Foo *foo(void) {
return malloc(sizeof(struct Foo));
}
फ़ंक्शन malloc
हीप पर ऑब्जेक्ट आवंटित करता है और उस ऑब्जेक्ट के लिए एक पॉइंटर लौटाता है। ध्यान दें कि शब्द "ऑब्जेक्ट" का उपयोग यहां शिथिल किया गया है, जिसका अर्थ ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग के अर्थ में ऑब्जेक्ट के बजाय "कुछ" है।
ढेर-आवंटित वस्तुओं का जीवनकाल प्रोग्रामर द्वारा नियंत्रित किया जाता है। इस ऑब्जेक्ट के लिए मेमोरी तब तक आरक्षित रहेगी जब तक कि प्रोग्रामर इसे फ्री नहीं करता, यानी कॉल करके free()
या जब तक प्रोग्राम बाहर नहीं निकलता।
संपादित करें : मैं इस सवाल को नोटिस करने में विफल रहा कि इसे C ++ प्रश्न के रूप में चिह्नित किया गया है। C ++ ऑपरेटर new
और new[]
उसी फ़ंक्शन को निष्पादित करते हैं malloc
। ऑपरेटरों delete
और के delete[]
अनुरूप हैं free
। जबकि new
और delete
आवंटित करने के लिए और सी ++ वस्तुओं विशेष रूप से इस्तेमाल किया जाना चाहिए, के उपयोग malloc
और free
सी ++ कोड में पूरी तरह से कानूनी है।
C में कोई भी गैर-तुच्छ प्रोजेक्ट लिखें और आपको यह इंगित करना होगा कि पॉइंटर्स का उपयोग कैसे / कब करना है। C ++ में आप ज्यादातर RAII- सक्षम ऑब्जेक्ट्स का उपयोग करेंगे जो आंतरिक रूप से पॉइंटर्स का प्रबंधन करते हैं, लेकिन C रॉ पॉइंटर्स में बहुत अधिक प्रचलित भूमिका है। किस तरह की परियोजना के लिए आपको क्या करना चाहिए, यह कुछ भी गैर-तुच्छ हो सकता है:
मैं पिछले एक की सलाह देता हूं।
लगभग सभी प्रोग्रामिंग समस्याओं कि संकेत के साथ हल किया जा सकता के अन्य सुरक्षित प्रकार के साथ हल किया जा सकता संदर्भ (की बात नहीं सी ++ संदर्भ है, लेकिन एक चर कहीं और संग्रहीत डेटा के मूल्य का उल्लेख होने के सामान्य सीएस अवधारणा)।
बिंदुओं का एक विशिष्ट निम्न-स्तरीय कार्यान्वयन द्वारा पॉइंटर्स , जहाँ आप सीधे मेमोरी पतों में हेरफेर कर सकते हैं, बहुत शक्तिशाली हैं, लेकिन उपयोग करने के लिए थोड़ा खतरनाक हो सकता है (जैसे, प्रोग्राम के बाहर मेमोरी स्थानों को इंगित करना)।
सीधे पॉइंटर्स का उपयोग करने का लाभ यह है कि वे किसी भी सुरक्षा जांच को नहीं करने से थोड़ा तेज़ होंगे। जावा जैसी भाषाएं जो सी-स्टाइल पॉइंटर्स को सीधे लागू नहीं करती हैं, एक मामूली प्रदर्शन हिट होगा, लेकिन कई प्रकार की मुश्किलों को कम कर देगा स्थितियों को डिबग करना।
जैसा कि आपको अप्रत्यक्ष की आवश्यकता क्यों है, सूची काफी लंबी है, लेकिन अनिवार्य रूप से दो प्रमुख विचार हैं:
selected_object
कि वस्तुओं में से एक के लिए एक संदर्भ है एक नए चर में वर्तमान वस्तु के मूल्य की नकल करने की तुलना में बहुत अधिक कुशल है।पिक्सेल स्तर छवि हेरफेर लगभग हमेशा आसान और तेजी से संकेत का उपयोग कर रहा है। कभी-कभी केवल पॉइंटर्स का उपयोग करना संभव है।
उपयोगकर्ता के बारे में बग को बताए बिना सतह के नीचे कई प्रोग्रामिंग भाषाओं में पॉइंटर्स का उपयोग किया जाता है। C / C ++ आपको केवल उन तक पहुंच प्रदान करता है।
उनका उपयोग कब करें: जितनी बार संभव हो, क्योंकि डेटा की प्रतिलिपि बनाना अक्षम है। उनका उपयोग कब न करें: जब आप दो प्रतियाँ चाहते हैं जिन्हें व्यक्तिगत रूप से बदला जा सकता है। (मूल रूप से ऑब्जेक्ट की सामग्री को मेमोरी में दूसरी जगह कॉपी करने और पॉइंटर वापस करने पर क्या खत्म होगा - इस बार ऑब्जेक्ट 2 की ओर इशारा करते हुए)
सी में किसी भी डेटा संरचना कार्यान्वयन के लिए पॉइंटर्स एक आवश्यक हिस्सा हैं और डेटा संरचना किसी भी गैर-तुच्छ कार्यक्रम का एक अनिवार्य हिस्सा हैं।
यदि आप यह जानना चाहते हैं कि यह क्यों है कि संकेत इतने महत्वपूर्ण हैं, तो मैं सुझाव दूंगा कि एक लिंक की गई सूची क्या है और किसी एक का उपयोग किए बिना लिखने की कोशिश कर रहा है। मैंने आपको एक असंभव चुनौती निर्धारित नहीं की है, (HINT: पॉइंटर्स का उपयोग मेमोरी में स्थानों को संदर्भित करने के लिए किया जाता है, आप सरणियों में चीजों को कैसे संदर्भित करते हैं?)।
एक वास्तविक जीवन उदाहरण के रूप में, एक सीमा ऑर्डर बुक का निर्माण।
उदाहरण के लिए, ITCH 4.1 फ़ीड में "प्रतिस्थापित" आदेशों की अवधारणा है, जहां कीमतें (और इसलिए, प्राथमिकता) बदल सकती हैं। आप आदेशों को निकालने और उन्हें अन्यत्र ले जाने में सक्षम होना चाहते हैं। पॉइंटर्स के साथ डबल-एंडेड कतार को लागू करने से ऑपरेशन बहुत आसान हो जाता है।
विभिन्न StackExchange साइटों का उपयोग करते हुए, मुझे एहसास हुआ कि इस तरह का प्रश्न पूछना प्रचलन में है। आलोचना और पतन के जोखिम पर, मैं ईमानदार रहूंगा। इसका मतलब केवल ट्रोल करना या भड़काना नहीं है, मैं केवल सवाल का ईमानदारी से मूल्यांकन करके मदद करने का मतलब हूं।
और यह आकलन निम्नानुसार है: यह एक बहुत ही अजीब सवाल है एक सी प्रोग्रामर से पूछें। बहुत कुछ यह सब कहते हैं, "मैं सी नहीं जानता।" यदि मैं थोड़ा और अधिक निष्ठापूर्वक विश्लेषण करता हूं, तो इस "प्रश्न" का अनुसरण करने का एक वचन है: "क्या कोई शॉर्टकट है जिसे मैं किसी अनुभवी सी प्रोग्रामर के ज्ञान को जल्दी और अचानक हासिल कर सकता हूं, बिना किसी समय के समर्पित स्वतंत्र अध्ययन के लिए? " कोई भी "उत्तर" जो कोई दे सकता है, वह अंतर्निहित अवधारणा और इसके उपयोग को समझने और समझने के लिए कोई विकल्प नहीं है।
मुझे लगता है कि वेब पर जाने और लोगों से यह पूछने की तुलना में, सी, फर्स्ट हैंड, सीखने के लिए अधिक रचनात्मक है। जब आप सी को अच्छी तरह से जानते हैं तो आप इस तरह के सवाल पूछने से परेशान नहीं होंगे, यह पूछने की तरह होगा "टूथब्रश का उपयोग करके कौन सी समस्याएं सबसे अच्छी तरह से हल होती हैं?"
भले ही पॉइंटर्स बड़ी मेमोरी ऑब्जेक्ट्स के साथ काम करते समय वास्तव में चमकते हैं, फिर भी उनके बिना ऐसा करने का एक तरीका है।
तथाकथित गतिशील प्रोग्रामिंग के लिए पॉइंटर बिल्कुल आवश्यक है , यह तब है जब आप नहीं जानते कि आपके प्रोग्राम को निष्पादित करने से पहले आपको कितनी मेमोरी की आवश्यकता होगी। डायनेमिक प्रोग्रामिंग में आप रनटाइम के दौरान मेमोरी चंक्स का अनुरोध कर सकते हैं और अपना डेटा उन में रख सकते हैं - इसलिए आपको उन डेटा चंक्स के साथ काम करने में सक्षम होने के लिए पॉइंटर या संदर्भ (अंतर यहां महत्वपूर्ण नहीं है) की आवश्यकता है।
जब तक आप रनटाइम के दौरान कुछ मेमोरी का दावा कर सकते हैं और अपने डेटा को नए अधिग्रहीत मेमोरी में रख सकते हैं, तब आप निम्न कार्य कर सकते हैं:
आपके पास स्वयं-विस्तारित डेटा संरचनाएं हो सकती हैं। वे संरचनाएं हैं जो अतिरिक्त मेमोरी का दावा करके खुद को विस्तारित कर सकते हैं जब तक कि उनकी क्षमता खत्म हो जाती है। प्रत्येक स्व-विस्तारित संरचना की मुख्य संपत्ति यह है कि इसमें छोटे मेमोरी ब्लॉक (संरचना के आधार पर नोड्स, सूची आइटम आदि) और प्रत्येक ब्लॉक में अन्य ब्लॉक (एस) के संदर्भ शामिल हैं। यह "लिंक्ड" संरचनाएं आधुनिक डेटा प्रकारों के अधिकांश का निर्माण करती हैं: रेखांकन, पेड़, सूचियां आदि।
आप OOP (ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग) प्रतिमान का उपयोग करके प्रोग्राम कर सकते हैं। संपूर्ण ओओपी प्रत्यक्ष चर का उपयोग नहीं करने पर आधारित है, लेकिन कक्षा के उदाहरणों (ऑब्जेक्ट्स) और उन्हें हेरफेर करने के संदर्भ में है। पॉइंटर्स के बिना कोई एकल उदाहरण मौजूद नहीं हो सकता है (भले ही यह बिना पॉइंटर्स के भी स्थिर-केवल कक्षाओं का उपयोग करना संभव हो, लेकिन यह अपवाद नहीं है)।
मजेदार, मैंने सिर्फ C ++ के बारे में एक सवाल का जवाब दिया और संकेत के बारे में बात की।
लघु संस्करण आपको तब तक चाहिए जब तक कि आपको 1) लाइब्रेरी का उपयोग करने की आवश्यकता न हो। 2) आपको एक अशक्त संदर्भ की आवश्यकता है।
यदि आपको एक सरणी, सूची, स्ट्रिंग आदि की आवश्यकता है, तो बस इसे स्टैक पर रखें और एक stl ऑब्जेक्ट का उपयोग करें। रिटर्निंग या पासिंग स्टाल ऑब्जेक्ट्स फास्ट (अनियंत्रित तथ्य) हैं क्योंकि उनके पास आंतरिक कोड है जो किसी ऑब्जेक्ट के बजाय एक पॉइंटर को कॉपी करता है और केवल डेटा कॉपी करेगा यदि आप इसे लिखते हैं। यह नियमित C ++ भी नया C ++ 11 नहीं है जो लाइब्रेरी लेखकों पर आसान बना देगा।
यदि आप एक पॉइंटर का उपयोग करते हैं तो सुनिश्चित करें कि यह इन दो स्थितियों में से एक में है। 1) आप इनपुट पास कर रहे हैं जो अशक्त हो सकता है। एक उदाहरण एक वैकल्पिक फ़ाइल नाम है। 2) यदि आप दूर स्वामित्व देना चाहते हैं। जैसे कि यदि आप पॉइंटर पास करते हैं या लौटाते हैं तो आपके पास इसकी कोई भी कॉपी शेष नहीं है और न ही आपके द्वारा दिए गए पॉइंटर का उपयोग करें
ptr=blah; func(ptr); //never use ptr again for here on out.
लेकिन मैंने बहुत लंबे समय तक पॉइंटर्स या स्मार्ट पॉइंटर्स का इस्तेमाल किया है और मैंने अपने एप्लिकेशन को प्रोफाइल किया है। यह बहुत तेज दौड़ता है।
अतिरिक्त नोट: मुझे लगता है कि मैं अपनी खुद की संरचना लिखने के लिए और मैं उन्हें चारों ओर से गुजरती हैं। तो मैं संकेत का उपयोग किए बिना यह कैसे करूं? इसकी एसटीएल कंटेनर नहीं है इसलिए रिफ से गुजरना धीमा है। मैं हमेशा अपनी डेटा सूची / देवताओं / नक्शे और ऐसे लोड करता हूं। मुझे याद नहीं है कि किसी भी वस्तु को वापस करना जब तक कि वह किसी प्रकार की सूची / मानचित्र न हो। एक तार भी नहीं। मैंने सिंगल ऑब्जेक्ट्स के लिए कोड को देखा और मैंने नोटिस किया कि मैं ऐसा कुछ करता हूं { MyStruct v; func(v, someinput); ... } void func(MyStruct&v, const D&someinput) { fillV; }
ताकि मैं (सिंगल) के संदर्भ में बहुत ज्यादा रिटर्न ऑब्जेक्ट्स (मल्टीपल) या प्रीलेक्लेट / पास (सिंगल) कर सकूं।
अब यदि आप लिख रहे हैं तो आप खुद के लिए deque, map आदि हैं, आपको पॉइंटर्स का उपयोग करना होगा। लेकिन आप की जरूरत नहीं है एसटीएल और संभवतः इस बारे में चिंता को बढ़ावा दें। आपको केवल डेटा और समाधान लिखने की आवश्यकता है। उन्हें रखने के लिए कंटेनर नहीं;)
मुझे उम्मीद है कि अब आप कभी भी पॉइंटर्स का उपयोग नहीं करेंगे: डी। उन कामों से निपटना सौभाग्य है जो आपको मजबूर करते हैं
मेमोरी-मैप्ड डिवाइस के साथ काम करने के लिए पॉइंटर्स बहुत उपयोगी हैं। आप एक संरचना को परिभाषित कर सकते हैं जो एक नियंत्रण रजिस्टर को दर्शाता है (कहता है), फिर इसे वास्तविक नियंत्रण रजिस्टर के पते पर मेमोरी में असाइन करें और इसे सीधे हेरफेर करें। यदि आप MMU ने सिस्टम मेमोरी स्पेस में मैप किया है, तो आप सीधे कार्ड या चिप पर ट्रांसफर बफर को भी इंगित कर सकते हैं।
मैं बिंदुओं को अपनी तर्जनी के रूप में देखता हूं, हम कुछ चीजों का उपयोग करते हैं:
कृपया इस खराब उत्तर को क्षमा करें
जैसा कि आपके प्रश्न को C ++ टैग किया गया है, मैं आपके प्रश्न का उत्तर उस भाषा के लिए दूंगा।
C ++ में पॉइंटर्स और रेफरेंस के बीच अंतर होता है, इसलिए दो परिदृश्य हैं जहां पॉइंटर्स (या स्मार्ट पॉइंटर्स) कुछ व्यवहारों को सुविधाजनक बनाने के लिए आवश्यक हैं। उनका उपयोग अन्य परिस्थितियों में किया जा सकता है, हालांकि आप पूछते हैं कि "उनका उपयोग कैसे करें" और अन्य सभी परिस्थितियों में बेहतर विकल्प हैं।
एक बेस क्लास पॉइंटर आपको एक वर्चुअल मेथड को कॉल करने की अनुमति देता है जो कि उस पॉइंटर के प्रकार पर निर्भर करता है जो पॉइंटर को इंगित करता है।
गतिशील रूप से (ढेर के बजाय ढेर पर) ऑब्जेक्ट बनाते समय पॉइंटर्स आवश्यक हैं। यह आवश्यक है जब आप चाहते हैं कि वस्तुओं को जीवन भर उस दायरे से अधिक लंबा होना चाहिए जिसमें इसे बनाया गया है।
"अच्छी परियोजनाओं या हल करने के लिए समस्याओं" के संदर्भ में, जैसा कि दूसरों ने पहले ही यहां कहा है, कोई भी गैर-तुच्छ परियोजना पॉइंटर्स का उपयोग करेगी।