कसने के लिए एक पॉइंटर को हटाना (T const *)


89

मेरे पास कास्ट पॉइंटर्स के संबंध में एक मूल प्रश्न है। मुझे किसी कांस्टेबल पॉइंटर का उपयोग करके किसी भी गैर-कास्ट सदस्य कार्यों को कॉल करने की अनुमति नहीं है। हालाँकि, मुझे एक कास्ट पॉइंटर पर ऐसा करने की अनुमति है:

delete p;

यह उस वर्ग के विनाशकर्ता को बुलाएगा जो संक्षेप में एक गैर-कास्ट 'विधि' है। इसकी अनुमति क्यों है? क्या सिर्फ इसका समर्थन करना है:

delete this;

या कोई और कारण है?

जवाबों:


112

इसका समर्थन करना है:

// dynamically create object that cannot be changed
const Foo * f = new Foo;

// use const member functions here

// delete it
delete f;

लेकिन ध्यान दें कि समस्या गतिशील रूप से निर्मित वस्तुओं तक सीमित नहीं है:

{
 const Foo f;
 // use it
} // destructor called here

अगर विध्वंसक कांस्टेबुल वस्तुओं पर नहीं बुलाया जा सकता है तो हम कास्ट ऑब्जेक्ट्स का उपयोग नहीं कर सकते हैं।


21
नवीनतम अपने संपादन के लिए +1। मुझे लगता है कि यह सही कारण है। कास्ट ऑब्जेक्ट के लिए स्वचालित विध्वंसक कॉल - लगभग समान रूप से हटाएं च; जहां च - सूचक कांस्टेबल।
बियाडा

const Foo * fया Foo const * fफू को कास्ट पॉइंटर नहीं है। यह फू फू कांस्टेबल है। Foo * const f फू के लिए एक कास्ट पॉइंटर है।
user11373693

48

इसे इस तरह से रखें - अगर इसकी अनुमति नहीं थी तो const_cast का उपयोग किए बिना कास्ट ऑब्जेक्ट को हटाने का कोई तरीका नहीं होगा।

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


3
विध्वंसक वस्तुओं को बल्कि हिंसक तरीकों से उत्परिवर्तित कर सकते हैं, इसलिए 'अपरिवर्तनीय' शब्द का यह कुछ विचित्र उपयोग होना चाहिए कि मुझे पहले से जानकारी नहीं थी ...
डार्थगिज़्का

1
@DarthGizka नहीं, विध्वंसक आपको उस राज्य से ले जाते हैं जहां कोई वस्तु है, जहां नहीं है। C ++ एक "म्यूटेशन" पोस्ट विनाश को देखने के लिए किसी भी विधि को परिभाषित नहीं करता है
Caleth

@ कैलथ: मानक नष्ट होने के बाद चलने के लिए मानक आपको वस्तु को देखने की अनुमति नहीं दे सकता है, लेकिन विनाश के कारण होने वाले दुष्प्रभावों को देखने के लिए आपको निश्चित रूप से अनुमति है। इसलिए परिस्थितियों को आसानी से 'अपरिवर्तनीय' वस्तु के म्यूटेशन के लिए व्यवस्थित किया जा सकता है। अमेरिका में, जब कोई शरीर नहीं होता है, तो मुकदमा चलाना मुश्किल है, लेकिन यह अभी भी हत्या है (और एक दोषी के लिए पर्याप्त अन्य सबूत भी हो सकते हैं)। बराबर असमानताएं।
डार्थजिस्का

6

मुझे किसी कांस्टेबल पॉइंटर का उपयोग करके किसी भी गैर-कास्ट सदस्य कार्यों को कॉल करने की अनुमति नहीं है।

हाँ तुम हो।

class Foo
{
public:
  void aNonConstMemberFunction();
};

Foo* const aConstPointer = new Foo;
aConstPointer->aNonConstMemberFunction(); // legal

const Foo* aPointerToConst = new Foo;
aPointerToConst->aNonConstMemberFunction(); // illegal

आपने एक नॉन-कास्ट ऑब्जेक्ट के लिए एक कॉन्स्टेंट पॉइंटर को भ्रमित किया है, नॉन-कॉस्ट पॉइंटर को कॉन्स ऑब्जेक्ट के लिए।

यह कहने के बाद,

delete aConstPointer; // legal
delete aPointerToConst; // legal

यहां पहले से ही अन्य उत्तरों द्वारा बताए गए कारणों के लिए या तो हटाना कानूनी है।


5

कंस्ट्रक्टर्स और डिस्ट्रक्टर्स को 'तरीकों' के रूप में नहीं देखा जाना चाहिए। वे वर्ग के एक ऑब्जेक्ट को इनिशियलाइज़ करने और फाड़ने के लिए विशेष निर्माण हैं।

'कॉन्स्ट पॉइंटर' से यह संकेत मिलता है कि वस्तु की स्थिति को तब नहीं बदला जाएगा जब उस पर परिचालन किया जाता है जबकि वह जीवित है।


5

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

यह अंतर अधिक स्पष्ट होगा यदि C ++ में पॉइंटर्स कमजोर संदर्भों की तरह व्यवहार किए जाते हैं, जैसे ही ऑब्जेक्ट नष्ट हो जाता है, इसके लिए सभी मौजूदा पॉइंटर्स को तुरंत सेट किया जाएगा 0। (इस तरह की चीज को सभी C ++ प्रोग्रामों पर लगाने के लिए रनटाइम के हिसाब से बहुत महंगा माना जाता है, और वास्तव में इसे पूरी तरह से विश्वसनीय बनाना असंभव है।)

अद्यतन : यह नौ साल बाद पढ़ना, यह वकील-ईश है। मुझे अब आपकी मूल प्रतिक्रिया समझ में आ रही है। म्यूटेशन को अस्वीकार करने के लिए लेकिन विनाश को स्पष्ट रूप से समस्याग्रस्त करने की अनुमति है। कॉन्स्ट पॉइंट / रेफरेंस का निहित अनुबंध यह है कि उनका अस्तित्व लक्ष्य ऑब्जेक्ट, उर्फ ​​स्वचालित कचरा संग्रह पर एक ब्लॉक के रूप में कार्य करेगा।

इसका सामान्य समाधान इसके बजाय लगभग किसी अन्य भाषा का उपयोग करना है।


यदि आप पॉइंटर्स द्वारा इंगित की गई चीज़ों को नष्ट नहीं कर सकते हैं, तो आप std::unique_ptr<const T>जीवन के अंत के साथ कैसे निपटते हैं?
केलथ

@ कैलेथ तब सी ++ में इसका कोई हल नहीं होगा। यह सामान्य समस्या का सिर्फ एक उदाहरण है: C ++ में कॉन्स्टेंट मॉडिफायर का अर्थ है "आप लक्ष्य को म्यूट नहीं कर सकते हैं, सिवाय एक अर्थ में जहां आप इसे पूरी तरह से मिटा सकते हैं और इसे अन्य सभी संदर्भों को अमान्य और अपरिभाषित व्यवहार के स्रोत" के रूप में प्रस्तुत कर सकते हैं। यही कारण है कि मुझे लगता है कि इस तरह के प्रश्न को अन्य भाषाओं पर विचार करने के लिए संकेत के रूप में कार्य करना चाहिए। इसमें यूबी छेद है जो एक अलग मूल दृष्टिकोण के बिना हल नहीं किया जा सकता है।
डैनियल ईयरविकर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.