आप किन परिस्थितियों में इस प्रकृति के कोड का उपयोग करना चाहते हैं c ++?
void foo(type *&in) {...}
void fii() {
type *choochoo;
...
foo(choochoo);
}
आप किन परिस्थितियों में इस प्रकृति के कोड का उपयोग करना चाहते हैं c ++?
void foo(type *&in) {...}
void fii() {
type *choochoo;
...
foo(choochoo);
}
जवाबों:
यदि आप पॉइंटर को इंगित करने वाले ऑब्जेक्ट के बजाय पॉइंटर को संशोधित करने की आवश्यकता है, तो आप संदर्भ द्वारा एक पॉइंटर पास करना चाहेंगे।
यह इसी वजह से है कि डबल पॉइंटर्स का उपयोग क्यों किया जाता है; पॉइंटर के संदर्भ में पॉइंटर्स का उपयोग करने की तुलना में थोड़ा सुरक्षित है।
delete
या उस मेमोरी में किसी अन्य स्थान पर पॉइंटर को रिबंड करने के लिए? या मुझे गलत लगा?
[]
ऑपरेटर को अधिभारित करेंगे । इसके लिए एक संभव (और वास्तव में स्वाभाविक) हस्ताक्षर होगा const T &operator[](size_t index) const
। लेकिन आप भी कर सकते थे T &operator[](size_t index)
। आप एक ही समय में दोनों हो सकते हैं। बाद वाला आपको चीजों को करने देगा myArray[jj] = 42
। उसी समय, आप अपने डेटा को पॉइंटर प्रदान नहीं कर रहे हैं, इसलिए कॉल करने वाला मेमोरी में गड़बड़ी नहीं कर सकता (उदाहरण के लिए इसे गलती से हटा दें)।
सी ++ प्रोग्रामर का 50% अपने डिलीटर्स को डिलीट करने के बाद सेट करना पसंद करते हैं:
template<typename T>
void moronic_delete(T*& p)
{
delete p;
p = nullptr;
}
संदर्भ के बिना, आप केवल सूचक की एक स्थानीय प्रति बदल रहे होंगे, कॉल करने वाले को प्रभावित नहीं करेंगे।
paranoid_delete
, लेकिन पिल्ला ने इसका नाम बदल दिया moronic_delete
। वह संभवत: अन्य 50% से संबंधित है;) वैसे भी, संक्षिप्त उत्तर यह है कि सेटिंग पॉइंटर्स को शून्य करने के delete
लिए लगभग कभी भी उपयोगी नहीं है (क्योंकि उन्हें गुंजाइश से बाहर जाना चाहिए, वैसे भी) और अक्सर "मुफ्त के बाद उपयोग" की पहचान में बाधा उत्पन्न होती है।
delete
है कि सामान्य रूप से बेवकूफ है। पिल्ला, मैंने कुछ गुगली किया, मैं नहीं देख सकता कि क्यों पूरी तरह से बेकार है (शायद मैं एक भयानक गुग्लर भी हूं;))। क्या आप थोड़ा और समझा सकते हैं या एक लिंक प्रदान कर सकते हैं?
डेविड का जवाब सही है, लेकिन अगर यह अभी भी थोड़ा सार है, तो यहां दो उदाहरण हैं:
आप स्मृति समस्याओं को पकड़ने के लिए सभी मुक्त संकेत शून्य करना चाहते हैं। सी-स्टाइल आप करेंगे:
void freeAndZero(void** ptr)
{
free(*ptr);
*ptr = 0;
}
void* ptr = malloc(...);
...
freeAndZero(&ptr);
C ++ में भी ऐसा ही करने के लिए, आप यह कर सकते हैं:
template<class T> void freeAndZero(T* &ptr)
{
delete ptr;
ptr = 0;
}
int* ptr = new int;
...
freeAndZero(ptr);
लिंक-सूचियों से निपटने के दौरान - अक्सर केवल अगले नोड के संकेत के रूप में प्रतिनिधित्व किया जाता है:
struct Node
{
value_t value;
Node* next;
};
इस स्थिति में, जब आप खाली सूची में सम्मिलित होते हैं, तो आपको आवश्यक रूप से आने वाले सूचक को बदलना होगा क्योंकि परिणाम NULL
अब सूचक नहीं है। यह एक ऐसा मामला है जहां आप किसी फ़ंक्शन से किसी बाहरी पॉइंटर को संशोधित करते हैं, इसलिए यह उसके हस्ताक्षर में पॉइंटर का संदर्भ होगा:
void insert(Node* &list)
{
...
if(!list) list = new Node(...);
...
}
इस प्रश्न में एक उदाहरण है ।
मुझे इस तरह से कोड का उपयोग करना पड़ा है ताकि पास में रखे पॉइंटर को मेमोरी आवंटित करने के लिए फ़ंक्शंस प्रदान की जा सके और एसटीएल का उपयोग करके मेरी कंपनी "ऑब्जेक्ट" मुझे वापस कर सके।
int iSizeOfArray(int* &piArray) {
piArray = new int[iNumberOfElements];
...
return iNumberOfElements;
}
यह अच्छा नहीं है, लेकिन पॉइंटर को संदर्भ द्वारा पारित किया जाना चाहिए (या डबल पॉइंटर का उपयोग करें)। यदि नहीं, तो मेमोरी को पॉइंटर की एक स्थानीय कॉपी के लिए आवंटित किया जाता है यदि यह मूल्य द्वारा पारित किया जाता है जिसके परिणामस्वरूप मेमोरी रिसाव होता है।
एक उदाहरण यह है कि जब आप एक पार्सर फ़ंक्शन लिखते हैं और इसे पढ़ने के लिए एक स्रोत पॉइंटर से पास करते हैं, यदि फ़ंक्शन को उस पॉइंटर को अंतिम वर्ण के पीछे आगे बढ़ाने के लिए माना जाता है जिसे पार्सर द्वारा सही ढंग से पहचाना गया है। एक पॉइंटर के संदर्भ का उपयोग करने से यह स्पष्ट हो जाता है कि फ़ंक्शन अपनी स्थिति को अपडेट करने के लिए मूल पॉइंटर को स्थानांतरित करेगा।
सामान्य तौर पर, यदि आप किसी फ़ंक्शन को पॉइंटर पास करना चाहते हैं, तो आप पॉइंटर्स के संदर्भों का उपयोग करते हैं और इसे ओरिजिनल प्रभावित किए बिना इसकी कॉपी को स्थानांतरित करने के बजाय उस मूल पॉइंटर को किसी अन्य स्थिति में ले जाने देते हैं।
एक और स्थिति जब आपको इसकी आवश्यकता हो सकती है यदि आपके पास पॉइंटर्स का संग्रह है और स्टाल एल्गोरिदम का उपयोग करके उन्हें बदलना चाहते हैं। C ++ 98 में for_each का उदाहरण।
struct Storage {
typedef std::list<Object*> ObjectList;
ObjectList objects;
void change() {
typedef void (*ChangeFunctionType)(Object*&);
std::for_each<ObjectList::iterator, ChangeFunctionType>
(objects.begin(), objects.end(), &Storage::changeObject);
}
static void changeObject(Object*& item) {
delete item;
item = 0;
if (someCondition) item = new Object();
}
};
अन्यथा, यदि आप changeObject (ऑब्जेक्ट * आइटम) हस्ताक्षर का उपयोग करते हैं तो आपके पास सूचक की प्रतिलिपि है, मूल नहीं।