programming - c++ in hindi



अगर एक पुनरावृत्त वैध है जाँच कर रहा है (8)

क्या यह जाँचने का कोई तरीका है कि क्या कोई इटरेटर डेरेफेरेंबल है

हाँ, gcc डिबगिंग कंटेनरों के साथ GNU एक्सटेंशन के रूप में उपलब्ध है। std::list आप __gnu_debug::list उपयोग कर सकते हैं। जैसे ही अमान्य पुनरावृत्ति का उपयोग करने का प्रयास किया जाएगा, निम्न कोड समाप्त हो जाएगा। डिबगिंग कंटेनर अतिरिक्त ओवरहेड लगाते हैं, जब वे डीबगिंग के दौरान ही लक्षित होते हैं।

#include <debug/list>

int main() {
  __gnu_debug::list<int> l;
  for (int i = 1; i < 10; i++) {
    l.push_back(i * 10);
  }

  auto itd = l.begin();
  itd++;
  l.erase(itd);

  /* now, in other place.. check if itd points to somewhere meaningful */
  if (itd != l.end()) {
    //  blablabla
  }
}

$ ./a.out 
/usr/include/c++/7/debug/safe_iterator.h:552:
Error: attempt to compare a singular iterator to a past-the-end iterator.

Objects involved in the operation:
    iterator "lhs" @ 0x0x7ffda4c57fc0 {
      type = __gnu_debug::_Safe_iterator<std::_List_iterator<int>, std::__debug::list<int, std::allocator<int> > > (mutable iterator);
      state = singular;
      references sequence with type 'std::__debug::list<int, std::allocator<int> >' @ 0x0x7ffda4c57ff0
    }
    iterator "rhs" @ 0x0x7ffda4c580c0 {
      type = __gnu_debug::_Safe_iterator<std::_List_iterator<int>, std::__debug::list<int, std::allocator<int> > > (mutable iterator);
      state = past-the-end;
      references sequence with type 'std::__debug::list<int, std::allocator<int> >' @ 0x0x7ffda4c57ff0
    }
Aborted (core dumped)

https://ffff65535.com

क्या यह जांचने का कोई तरीका है कि क्या एक इट्रेटर (चाहे वह एक वेक्टर, एक सूची, एक deque ...) से है (अभी भी) अनुमेय है, अर्थात अमान्य नहीं किया गया है?

मैं try कर रहा हूँ catch का उपयोग कर रहा है, लेकिन वहाँ यह करने के लिए एक और अधिक सीधा रास्ता है?

उदाहरण: (जो काम नहीं करता है)

list<int> l;
for (i = 1; i<10; i++) {
    l.push_back(i * 10);
}

itd = l.begin();
itd++;
if (something) {
    l.erase(itd);
}

/* now, in other place.. check if itd points to somewhere meaningful */
if (itd != l.end())
{
    //  blablabla
}

क्या यह जांचने का कोई तरीका है कि क्या एक इट्रेटर (चाहे वह एक वेक्टर, एक सूची, एक deque ...) से है (अभी भी) अनुमेय है, अर्थात अमान्य नहीं किया गया है?

नहीं, वहाँ नहीं है। उदाहरण के लिए, इसके बजाय आपको कंटेनर तक पहुंच को नियंत्रित करने की आवश्यकता है, उदाहरण के लिए:

  • आपके धागे को कंटेनर को संशोधित नहीं करना चाहिए (पुनरावृत्त को अमान्य करना), जबकि यह अभी भी उस कंटेनर के लिए एक त्वरित पुनरावृत्ति का उपयोग कर रहा है

  • यदि कोई खतरा है कि अन्य धागे कंटेनर को संशोधित कर सकते हैं, जब आपका धागा पुनरावृत्त हो रहा है, तो इस परिदृश्य को सुरक्षित बनाने के लिए आपके धागे को कंटेनर पर किसी प्रकार का ताला प्राप्त करना होगा (ताकि यह अन्य धागे को कंटेनर को संशोधित करने से रोकता है जबकि यह एक पुनरावृत्ति का उपयोग कर रहा है)

एक अपवाद को पकड़ने की तरह काम के आसपास काम नहीं करेगा।

यह अधिक सामान्य समस्या का एक विशिष्ट उदाहरण है, "क्या मैं परीक्षण / पता लगा सकता हूं कि क्या एक संकेतक वैध है?", जिसका उत्तर आमतौर पर "नहीं, आप इसके लिए परीक्षण नहीं कर सकते हैं: इसके बजाय आपको सभी मेमोरी आवंटन का प्रबंधन करना होगा और यह जानने के लिए कि क्या कोई संकेत सूचक अभी भी वैध है "।


आमतौर पर आप इसे जांच कर परखते हैं कि क्या यह अंत से अलग है (), जैसे

if (it != container.end())
{
   // then dereference
}

इसके अलावा तर्क को बदलने के लिए अपवाद हैंडलिंग का उपयोग डिजाइन और प्रदर्शन के मामले में खराब है। आपका प्रश्न बहुत अच्छा है और यह निश्चित रूप से आपके कोड में एक प्रतिस्थापन के लायक है। नामों की तरह अपवाद से निपटने का उपयोग केवल दुर्लभ अप्रत्याशित मुद्दों के लिए किया जाएगा।


किसी भी std कंटेनर के कार्य के प्रकार के पैरामीटर (जैसा कि आपने अपने प्रश्न में सूचीबद्ध किया है, अर्थात यह एक वेक्टर, एक सूची, एक deque से है ...) हमेशा इस कंटेनर का पुनरावृत्त होता है।

यह फ़ंक्शन कंटेनर से बाहर करने के लिए पहले दिए गए पुनरावृत्ति का उपयोग करता है जो कि इस पुनरावृत्ति को इंगित करता है और यहां तक ​​कि अनुसरण करने वाले भी। कुछ कंटेनर केवल एक तत्व को एक पुनरावृत्त के लिए मिटाते हैं, और कुछ अन्य कंटेनर कंटेनर के अंत तक एक पुनरावृत्ति (इस पुनरावृत्त द्वारा इंगित किए गए तत्व सहित) के बाद सभी तत्वों को मिटा देते हैं। यदि मिटाया गया कार्य दो पुनरावृत्तियों को प्राप्त करता है, तो दो तत्वों, जो प्रत्येक पुनरावर्तक द्वारा इंगित किए जाते हैं, कंटेनर से मिटा दिए जाते हैं और उनके बीच के बाकी सभी को कंटेनर से भी मिटा दिया जाता है, लेकिन बिंदु यह है कि मिटा देने के लिए पारित होने वाला प्रत्येक पुनरावृत्ति किसी भी std कंटेनर का कार्य अमान्य हो जाता है! इसके अलावा :

प्रत्येक पुनरावृत्ति जो किसी ऐसे तत्व की ओर इशारा कर रहा था जिसे कंटेनर से मिटा दिया गया है वह अमान्य हो जाता है, लेकिन यह कंटेनर के अंत को पारित नहीं करता है!

इसका मतलब यह है कि एक पुनरावृत्ति जो कुछ तत्व को इंगित कर रहा था जिसे कंटेनर से मिटा दिया गया है, उसकी तुलना कंटेनर से नहीं की जा सकती है। ()। यह पुनरावृत्ति अमान्य है, और इसलिए यह निष्क्रिय नहीं है, अर्थात आप न तो * और न ही -> ऑपरेटरों का उपयोग नहीं कर सकते हैं, यह भी वृद्धि योग्य नहीं है, अर्थात आप ++ ऑपरेटर का उपयोग नहीं कर सकते हैं, और यह भी घटने योग्य नहीं है, अर्थात आप उपयोग नहीं कर सकते। परिचालक।

यह भी तुलनीय नहीं है !!! IE आप भी न तो == और न ही! = ऑपरेटरों का उपयोग नहीं कर सकते

वास्तव में आप किसी भी ऑपरेटर का उपयोग नहीं कर सकते हैं जो घोषित किया गया है और एसटीडी इटरेटर में परिभाषित किया गया है। आप इस सूचक के साथ कुछ भी नहीं कर सकते, जैसे कि नल पॉइंटर।

अमान्य पुनरावृत्ति के साथ कुछ करने से प्रोग्राम तुरंत बंद हो जाता है और यहां तक ​​कि प्रोग्राम क्रैश हो जाता है और एक डायलॉग विंडो दिखाई देती है। कार्यक्रम जारी रखने का कोई तरीका नहीं है कि आप क्या विकल्प चुनते हैं, आप किस बटन पर क्लिक करते हैं। आप बस एबोर्ट बटन पर क्लिक करके प्रोग्राम और प्रक्रिया को समाप्त कर सकते हैं।

जब तक आप या तो इसे कंटेनर की शुरुआत में सेट नहीं कर सकते, या इसे अनदेखा नहीं करते हैं, तब तक आप एक अमान्य पुनरावृत्ति के साथ कुछ और नहीं करते हैं।

लेकिन इससे पहले कि आप यह तय करें कि एक इटेरेटर के साथ क्या करना है, पहले आपको पता होना चाहिए कि क्या यह इटरेटर या तो अमान्य है या नहीं, यदि आप उस कंटेनर के इरेज़ फ़ंक्शन को कहते हैं जिसका आप उपयोग कर रहे हैं।

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

bool IsNull(list<int>::iterator& i) //In your example, you have used list<int>, but if your container is not list, then you have to change this parameter to the type of the container you are using, if it is either a vector or deque, and also the type of the element inside the container if necessary.
{
    byte buffer[sizeof(i)];
    memset(buffer, 0, sizeof(i));
    memcpy(buffer, &i, sizeof(i));
    return *buffer == 0; //I found that the size of any iterator is 12 bytes long. I also found that if the first byte of the iterator that I copy to the buffer is zero, then the iterator is invalid. Otherwise it is valid. I like to call invalid iterators also as "null iterators".
}

मैंने इस फ़ंक्शन का परीक्षण पहले ही कर लिया है, जब मैंने इसे वहां पोस्ट किया और पाया कि यह फ़ंक्शन मेरे लिए काम कर रहा है।

मुझे बहुत उम्मीद है कि मैंने आपके सवाल का पूरी तरह से जवाब दिया है और आपकी बहुत मदद की है!


गैर-पोर्टेबल उत्तर: हां - विजुअल स्टूडियो में

विजुअल स्टूडियो के एसटीएल पुनरावृत्तियों में एक "डीबगिंग" मोड है जो वास्तव में ऐसा करता है। आप इसे शिप बिल्ड्स (ओवरहेड) में सक्षम नहीं करना चाहेंगे, लेकिन चेक किए गए बिल्ड में उपयोगी है।

इसके बारे में VC10 पर here पढ़ें (यह प्रणाली वास्तव में हर रिलीज़ को बदल सकती है, इसलिए डॉक्स को आपके संस्करण के लिए विशिष्ट ढूंढें)।

इसके अलावा, मुझे जोड़ना चाहिए: दृश्य स्टूडियो में डिबग पुनरावृत्तियों को तुरंत उपयोग करने के लिए डिज़ाइन किया जाता है जब आप उनका उपयोग करते हैं (बजाय अपरिभाषित व्यवहार); अपने राज्य की "क्वेरी" की अनुमति नहीं है।


जैसा कि जेधान ने कहा, यदि पुनरावृत्ति को अमान्य नहीं किया गया था और एक कंटेनर में इंगित करता है, तो आप इसे container.end() से जोड़कर जांच कर सकते हैं। container.end()

ध्यान दें, हालांकि, अगर इट्रेटर एकवचन है - क्योंकि यह आरंभिक नहीं था या कंटेनर पर म्यूटेशन ऑपरेशन के बाद यह अमान्य हो गया (वेक्टर के पुनरावृत्तियों को अमान्य कर दिया जाता है जब आप वेक्टर की क्षमता बढ़ाते हैं, उदाहरण के लिए) - एकमात्र ऑपरेशन जो आपको इस पर कार्य करने की अनुमति है। दूसरे शब्दों में, आप जाँच नहीं कर सकते हैं कि एक इटैलर विलक्षण है या नहीं।

std::vector<int>::iterator iter = vec.begin();
vec.resize(vec.capacity() + 1);
// iter is now singular, you may only perform assignment on it,
// there is no way in general to determine whether it is singular or not

वेतन वृद्धि के साथ उपयोग करें:

   if (something) l.erase(itd++);

इसलिए आप पुनरावृत्ति की वैधता का परीक्षण कर सकते हैं।


if (iterator != container.end()) {
   iterator is dereferencable !
}

यदि आपका पुनरावृत्ति करने वाला बराबर container.end() , और आपत्तिजनक नहीं हैं, तो आप कुछ गलत कर रहे हैं।





dereference