2010-05-17 9 views
13

मुझे boost :: check_delete के उद्देश्य को समझ में नहीं आता है। प्रलेखन कहते हैं:बूस्ट का उद्देश्य :: check_delete

सी ++ स्टैंडर्ड अनुमति देता है, में 5.3.5/5, को अधूरा वर्ग प्रकार के संकेत हटाएं-अभिव्यक्ति के साथ हटा दिया। जब कक्षा में एक गैर-तुच्छ विनाशक होता है, या वर्ग-विशिष्ट ऑपरेटर हटाता है, तो व्यवहार अपरिभाषित है। कुछ कंपाइलर्स चेतावनी जारी करते हैं जब एक अपूर्ण प्रकार हटा दिया जाता है, लेकिन दुर्भाग्य से, सभी नहीं करते हैं, और प्रोग्रामर कभी-कभी को अनदेखा करते हैं या चेतावनियां अक्षम करते हैं।

आपूर्ति समारोह और वर्ग टेम्पलेट्स इन समस्याओं को रोकने के लिए, के रूप में वे एक पूरी प्रकार की आवश्यकता होती है, और नहीं तो एक संकलन त्रुटि कारण इस्तेमाल किया जा सकता।

तो सी ++ मानक आप अधूरा प्रकार, यदि प्रकार एक गैर तुच्छ नाशक है जो अपरिभाषित व्यवहार का कारण बनता है हटाने देती है। क्या? एक अपूर्ण प्रकार का कोई विनाशक कैसे हो सकता है? एक अधूरा प्रकार सिर्फ एक प्रोटोटाइप नहीं है?

// this file does not include the definition of foo 

class foo; 

void bad(foo *f) 
{ 
    delete f; // undefined behavior if there exists foo::~foo 
} 

हकीकत में, foo की परिभाषा कुछ ऐसा दिखाई देगा:

+0

क्या यह स्लाइसिंग के साथ कुछ करने के लिए हो सकता है? http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c – Cogwheel

उत्तर

16

एक अधूरी प्रकार का सबसे आम उदाहरण है कि एक ही घोषित किया गया है है

class foo 
{ 
public: 
    ~foo() { ... }; 
}; 

लेकिन अगर शीर्ष कोड ने वर्ग परिभाषा को 'देखा' नहीं है और केवल वर्ग घोषणा को देखता है, कोड संकलित होगा।

+0

कक्षा टेम्पलेट में * पूर्ण * की आवश्यकता क्यों हो सकती है? –

+3

'check_delete' प्रकार पर 'sizeof' को कॉल करने का प्रयास करता है, और जाहिर है कि यदि प्रकार अधूरा है तो संकलक त्रुटि का कारण बनता है। – Channel72

+0

@ चैनल 72: आपको पता होना क्यों सी ++ इसे संकलक त्रुटि के रूप में परिभाषित नहीं करता है? –

2

सी ++ आपको उन चर पर delete का उपयोग करने की अनुमति देता है, जो उस समय अपूर्ण प्रकार के पॉइंटर्स हैं।

struct S; // incomplete 

int main() { 
    S* s = NULL; 
    delete s; // legal 
} 

संकलक उस बिंदु क्या S वास्तव में है पर पता नहीं है। यदि यह S में एक गैर-तुच्छ विनाशक है, तो उस समस्या का पता लगाने के लिए संकलक की आवश्यकता नहीं है।

व्यावहारिक रूप से बोलते हुए, शायद ऐसा होता है कि जब संकलक delete अधूरे प्रकार पर निर्देश का सामना करता है, तो यह उस कॉल के लिए भर जाता है जो यह अपेक्षा करता है कि यह सामान्य संकलक-डिफ़ॉल्ट डिफक्टर उत्पन्न करता है। और अगर विनाशक बन जाता है, तो सबकुछ ठीक है। लेकिन अगर यह पता चला है कि S में एक गैर-तुच्छ विनाशक है, या यदि यह हटाने की अपनी विशेष विधि प्रदान करता है, तो पहले में भरने वाला संकलक गलत होगा। संकलक, हालांकि, यह मानने की अनुमति है कि यह सही ढंग से delete निर्देश संकलित करता है और कभी वापस नहीं देखता है। जब वह धारणा गलत होती है, तो आपको अपरिभाषित व्यवहार मिल जाएगा।

बूस्ट फ़ंक्शन यह सुनिश्चित करता है कि इसे केवल पूर्ण प्रकारों पर ही बुलाया जाए, इस प्रकार अपूर्ण प्रकार से अपरिभाषित व्यवहार से परहेज किया जा सके।

Foo.h:

4

निम्नलिखित पर विचार करें

#ifndef Foo_H 
#define Foo_H 
#include <boost/scoped_ptr.hpp> 
#include <boost/utility.hpp> 

class Foo : private boost::noncopyable 
{ 
public: 
    Foo(); 
    ~Foo(); 

    void do_something_interesting(); 

private: 
    class Impl; // incomplete type 
    boost::scoped_ptr<Impl> impl; 
}; 

#endif 

फू।सीपीपी:

#include "Foo.h" 
#include <string> 
#include <iostream> 

class Foo::Impl 
{ 
public: 
    Impl() : name("Foo::Impl") 
    {} 

    void say_hi() 
    { std::cout << name << " says hi!" << std::endl; } 

    std::string name; 
}; 

Foo::Foo() 
: impl(new Impl) 
{} 

Foo::~Foo() 
{} 

void Foo::do_something_interesting() 
{ impl->say_hi(); } 

इस (काल्पनिक) उदाहरण को देखते हुए, आप या तो Foo::Foo या Foo::~Foo इनलाइन नहीं कर सकते क्योंकि प्रकार अधूरा है। संदर्भ में दोनों को परिभाषित करके जहां Foo::Impl टाइप एक पूर्ण प्रकार है, आप प्रकार को सुरक्षित रूप से हटा सकते हैं। boost::checked_delete यह सुरक्षा आपके लिए जांच करता है, और यह पूरी तरह से एक संकलन समय लागत है। यदि आप या तो Foo::~Foo इनलाइन करते हैं या इसे पूरी तरह से छोड़ देते हैं, तो आप boost::checked_delete से एक त्रुटि प्राप्त करेंगे जहां भी आप Foo उदाहरण को नष्ट करने का प्रयास करते हैं।

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