2009-12-07 24 views
19

मैं सिर्फ इस article पढ़ रहा था और इसलिए लोगों को सलाह चाहता था:क्या इसे "हटाएं" को सदस्य विधि के भीतर से बुलाया जाना चाहिए?

प्रश्न: delete this; एक सदस्य विधि के भीतर से बुलाया जाना चाहिए?

+7

एक बेहतर सवाल "क्या आप कभी इसका उपयोग कर सकते हैं 'इसे हटाएं? उत्तर - नहीं। –

+13

दुर्लभ अवसर होते हैं जब इसे "इसे हटाएं" कहने के लिए उचित होता है - लेकिन वे बहुत दुर्लभ हैं ... –

+2

@Neil: आप किसी सदस्य फ़ंक्शन के अलावा कहीं भी 'इसे हटाएं' (या किसी कन्स्ट्रक्टर में प्रारंभकर्ता, मुझे लगता है, लेकिन यह सिर्फ मेरे दिमाग को चोट पहुंचाता है)। तो आपको इसे पूरी तरह से उत्तर के रूप में पोस्ट करना चाहिए। –

उत्तर

33

आम तौर पर यह एक बुरा विचार है, लेकिन यह कभी-कभी उपयोगी होता है।

यह तब तक सुरक्षित है जब तक आप हटाए जाने के बाद किसी भी सदस्य चर का उपयोग नहीं करते हैं, और जब तक कि इस विधि को कॉल करने वाले क्लाइंट समझते हैं कि यह ऑब्जेक्ट को हटा सकता है।

जब यह उपयोगी है का एक अच्छा उदाहरण है, तो अपनी कक्षा संदर्भ गिनती को रोजगार:

void Ref() { 
    m_References++; 
} 

void Deref() { 
    m_References--; 
    if (m_References == 0) { 
    delete this; 
    } 
} 
+3

आप "लटकते पॉइंटर्स" का जादू कैसे करते हैं? – elcuco

+16

आपने इसे ठीक से लिखा है, एल्कोको। अापका नजरिया क्या है? क्या आप डरते हैं कि एक वस्तु स्वयं को नष्ट करने से अधिक खतरनाक पॉइंटर्स पैदा करेगी, अगर कुछ और वस्तु वस्तु को नष्ट कर देगी? 'foo-> deref()' 'से भी बदतर नहीं है (foo-> deref() == 0) foo को हटाएं;'। इसके अलावा, यदि संदर्भ संख्या शून्य है, तो किसी भी अन्य बिंदुओं को किसी भी तरह से लटकने के लिए नहीं छोड़े गए हैं। –

1

ऐसा करने के लिए बहुत अच्छे कारण के बिना नहीं।

समस्या यह है कि जब आप किसी सदस्य फ़ंक्शन में delete this पर कॉल करते हैं, तो आप एक बुरा दुष्प्रभाव बना रहे हैं - कॉलर के पास अभी भी आपके उदाहरण का संदर्भ है जो अब पूरी तरह से अमान्य है।

यह शायद अपेक्षित व्यवहार नहीं है, इसलिए यह आसानी से खराब कीड़े का कारण बन सकता है।

कहा जा रहा है कि, यह उचित है (मैंने कुछ पुस्तकालयों के साथ कुछ स्मृति प्रबंधन योजनाएं देखी हैं, जहां आप स्पष्ट रूप से कक्षाओं में विधियों को बनाते हैं जो मुख्य रूप से भाषा अंतःक्रियाशीलता के लिए)। आम तौर पर, मुझे लगता है कि यह बुरा अभ्यास है, यद्यपि।

12

मुझे लगता है कि वहाँ वास्तव में 2 यहाँ सवाल

इस हटाया नहीं जा सकता वैध एक सदस्य विधि से कहा जा रहे हैं ?

हां। यह तब तक वैध है जब तक आप उपयोग से बहुत सावधान रहें।

इसे किसी सदस्य विधि के भीतर उपयोग करना चाहिए?

बहुत विशिष्ट मामलों में यह आवश्यक है। उदाहरण के लिए कुछ प्रकार के स्मार्ट पॉइंटर्स पॉइंटर को मारने के लिए delete this पैटर्न का उपयोग करते हैं। उदाहरण: CComPtr<> शैली।

हालांकि स्मार्ट पॉइंटर्स के अलावा, इसे तब तक टालना चाहिए जब तक कि आपके पास ऐसा करने का कोई अच्छा कारण न हो। फिर भी, मैं सावधानी से अपने परिदृश्य पर पुनर्विचार करता हूं और देखता हूं कि इसके आसपास कोई रास्ता है या नहीं।

5

हां, ऐसे कुछ मामले हैं जहां यह आम है।

संदर्भ गिनती:

void release() 
{ 
    cnt--; 
    if (cnt == 0) 
    delete this; 
} 

जीयूआई प्रोग्रामिंग। कुछ ढांचे में, जब कोई उपयोगकर्ता विंडो बंद करता है तो खिड़की के लिए खुद को हटाना आम बात है।

11

हाँ आप कर सकते हैं और here's कब और क्यों

+1

या यहां एक लिंक है जो आपको यह नहीं करना चाहिए कि आप इसे क्यों नहीं करना चाहिए इसके बीच खतरे और पढ़ना बताते हैं। –

0

तुम कर सकते हो, एक सदस्य समारोह में अपनी अंतिम तत्व प्रदान की, और कहा कि वापसी के बाद आप उस वस्तु कभी अस्तित्व में भूल जाते हैं की एक अच्छी व्याख्या .... लेकिन हाँ, उस लेख की तरह पूछता है ... आप ऐसा क्यों करना चाहते हैं?मुझे नहीं पता कि मानक क्या कहता है, लेकिन यह मुझे एक अजीब लग रहा है: पी

मुझे लगता है कि यह कभी भी एक गोटो स्टेटमेंट का उपयोग करना चाहिए, और मैं व्यक्तिगत रूप से सी में संसाधनों को साफ करने के लिए गोटो का उपयोग करता हूं कभी-कभी, विशेष रूप से असाधारण स्थितियों के तहत।

मुझे आश्चर्य है कि क्या साझा राज्य निहितार्थ (फजी बयान मुझे पता है) कर रहे हैं: पी

1

कुछ सूत्रण पुस्तकालयों इसका इस्तेमाल जब एक ऑटो धागा समाप्ति पर नष्ट लागू करने।

void Thread::threadFunc() 
{ 
    doRun(); 

    if(this->destroyOnExit == true) 
     delete this; 
} 
1

यह अक्सर एमएफसी दिनों में उपयोग किया जाता था। IIRC अंतिम संदेश एक खिड़की प्राप्त करता WM_NCDESTROY है, इसके बाद से आप delete this कह सकते हैं, यह मानते हुए आप निश्चित रूप से पीड़न कामुक के कुछ फार्म थे (हालांकि MFC ही बार मुझे लगता है कि पर यह काम किया।)

+1

हां, एमएफसी ऑनडेस्ट्रॉय() फ़ंक्शन करता है :) –

5

नीचे वोट के लिए तैयार हो रही है।

चाहिए यह: नहीं
कर सकते हैं यह तकनीकी तौर पर: हाँ
यह एक अच्छा विचार है: बिल्कुल नहीं।
क्या स्थिति उपयोगी है: बेशक। यदि आप सी ++ फू बहुत मजबूत हैं। लेकिन ज्यादातर लोग अच्छे नहीं हैं। तो केवल तभी ऐसा करें जब आपके पास काम करने वाले लोगों की एक टीम सभ्य कोड समीक्षा करने में सक्षम हो।

क्यों:
एक वस्तु को पता है कि यह गतिशील रूप से आवंटित किया गया है (और इस प्रकार को हटाने की जरूरत है) या एक सामान्य वस्तु है (और इस प्रकार हटाया नहीं जाना चाहिए) और इस तरह यह decidide कैसे कर सकते हैं के लिए कोई तरीका नहीं है मौसम इसे हटाया जाना चाहिए। इस प्रकार यदि कोई वस्तु स्वयं को हटा रही है तो मेरी राय में डिजाइन के साथ बहुत कुछ गलत है।

यदि आपके पास ऐसी ऑब्जेक्ट है जिसे प्रबंधन की आवश्यकता है तो आपको प्रबंधन (इसलिए स्मार्ट पॉइंटर्स) करने के लिए एक अलग ऑब्जेक्ट लिखना चाहिए। ऑब्जेक्ट को यह करने दें कि यह क्या अच्छा है, फिर ऑब्जेक्ट के प्रबंधन को किसी अन्य ऑब्जेक्ट में विभाजित करें।

+0

यह भी ध्यान दें कि "कक्षा के बाहर" आप अभी भी सुनिश्चित नहीं हो सकते हैं कि एक पॉइंटर वास्तव में गतिशील रूप से आवंटित ऑब्जेक्ट को इंगित करता है, उदाहरण के लिए स्वचालित या स्थैतिक वस्तु नहीं। (वास्तव में मुझे लगता है कि कई मामलों में आप सदस्य समारोह में भी कम यकीन कर सकते हैं ...) तो 'पी' हटाएं जोखिम भरा है चाहे यह 'पी' है या नहीं। –

+0

@ एडम: धन्यवाद। लेकिन जैसा कि बताया गया है कि यह उपयोगी हो सकता है। लेकिन आधुनिक सी ++ में ऑब्जेक्ट के कार्यान्वयन से ऑब्जेक्ट के प्रबंधन को अलग करने के लिए बेहतर अभ्यास माना जाता है (इसलिए स्मार्ट पॉइंटर्स अब COM की बजाय उपयोग किए जाते हैं)। यह भी ध्यान रखें कि एक प्रबंधन वस्तु आसानी से अनुदान दे सकती है कि जिस वस्तु का प्रबंधन होता है वह गतिशील रूप से आवंटित किया जाता है ताकि यह पूरी तरह से झूठा आधार हो। –

0

हां। सभी उत्तरों की तरह, यदि आप 100% सुनिश्चित हैं कि delete this के बाद कक्षा का डेटा उपयोग नहीं किया जाएगा।

उदाहरण के लिए, एक परियोजना में:

void Test() 
MyClass * Someclass = new MyClass; 
SomeClass->DoYourThing(); 
SomeClass->KillYourself(); 
return; 

void MyClass::DoYourThing() { return; } 
void MyClass::KillYourself() {delete this;} 

बहुत साधारण स्पष्टीकरण, परियोजना है कि प्रकार की वस्तुओं के लिए स्मृति प्रबंधन के हिस्से के रूप में इस्तेमाल किया delete this;; उनके कन्स्ट्रक्टर ने उन्हें उस प्रकार के वर्गों की एक निजी सूची में उपयोग में जोड़ा, और जब उन्हें नष्ट कर दिया गया था तब खुद को हटा दिया और फिर खुद को हटा दिया (यह विनाशक में नहीं था)। उस वर्ग के किसी भी वस्तुओं है कि स्वयं नहीं हटाए था जब कार्यक्रम अपने अंतिम बिंदु पर पहुंच गया तो सभी उनके KillYourself() बराबर एक स्थिर सदस्य समारोह CleanYourselves()

0
  1. delete this एक गैर सदस्य समारोह से नहीं कहा जा सकता :)
  2. से कहा जाता था
  3. यह तब तक करना एक बुरा विचार है जब तक आप इसके परिणामों को समझ नहीं लेते।
0

हालांकि इस धागे से सीधे संबंधित नहीं है, मैं इसे स्पष्ट करना चाहता हूं। मैं एक सवाल है कि एक स्थिति को देखते हुए कहा गया था:

int* a = new int ; 
int* b = a ; 
delete a; 

अब अगले स्टेटमेंट सुरक्षित है?

cout<<*b ;

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

नोट: कोई डाउनवॉटिंग कृपया, यह सिर्फ एक स्पष्टीकरण है

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

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