2009-04-16 5 views
9

मैं एक संकलक त्रुटि है कि मेरे पास खास मतलब नहीं था में भाग:क्यों निर्माण कार्य auto_ptr नहीं है का उपयोग कर = वाक्य रचना

#include <memory> 
using namespace std; 

auto_ptr<Table> table = db->query("select * from t"); 

त्रुटि: गैर अदिश प्रकार के लिए 'टेबल *' रूपांतरण ' std :: auto_ptr < तालिका> '

अनुरोध किया हालांकि, निम्न पंक्ति करता है काम:

auto_ptr<Table> table(db->query("select * from t")); 

क्या यह निर्माता है कि यह के रूप में मैं उम्मीद काम करने से रोकता के इस definiton बारे में है? मैंने सोचा कि शुरुआती घोषणाएं रचनाकारों का इस्तेमाल करती हैं।

explicit 
auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { } 

उत्तर

17

यह "स्पष्ट" कीवर्ड है:

मेरा अनुमान है कि आप काम के प्रपत्र जरूरत है एक और की तरह के बाद कई प्रश्नों का उपयोग करने के लिए है।

template <typename T> 
struct foo 
{ 
    explicit foo(T const *) 
    { 
    } 
}; 


template <typename T> 
struct bar 
{ 
    bar(T const *) 
    { 
    } 
}; 


int main(int argc, char **argv) 
{ 
    int a; 
    foo<int> f = &a; // doesn't work 
    bar<int> b = &a; // works 
} 

"स्पष्ट" कीवर्ड अंतर्निहित प्रकार रूपांतरणों के लिए निर्माता को उपयोग करने से रोकता है। निम्नलिखित दो समारोह प्रोटोटाइप पर विचार करें:

void baz(foo<int> const &); 
void quux(bar<int> const &); 
उन परिभाषाओं के साथ

, किसी पूर्णांक सूचक के साथ दोनों कार्यों से कॉल करके:

baz(&a); // fails 
quux(&a); // succeeds 

quux के मामले में, अपने पूर्णांक सूचक परोक्ष एक बार में परिवर्तित कर दिया गया।

संपादित करें: दूसरे लोग क्या टिप्पणी की जिस पर विस्तार करने के लिए निम्न (बल्कि मूर्खतापूर्ण) कोड पर विचार करें:

void bar(std::auto_ptr<int>); 


int main(int argc, char **argv) 
{ 
    bar(new int()); // probably what you want. 

    int a; 
    bar(&a); // ouch. auto_ptr would try to delete a at the end of the 
      // parameter's scope 

    int * b = new int(); 
    bar(b); 
    *b = 42; // more subtle version of the above. 
} 
+0

उह। बस जब मैं खुद को यह मानता हूं कि मुझे वास्तव में auto_ptr के लिए उपयोग मिला है, तो यह डिज़ाइन मुझे चेहरे पर smacks। पुराने हटाने के लिए वापस जाओ। –

+2

इसके लिए auto_ptr को न छोड़ें। बस स्पष्ट कन्स्ट्रक्टर का उपयोग करें: auto_ptr

तालिका (डीबी-> क्वेरी ("टी से चुनें *)); या साझा_ptr को ले जाएं। – Eclipse

+1

कन्स्ट्रक्टर स्पष्ट होने के लिए बहुत अच्छा कारण है। यह आपको आकस्मिक गलतियों से बचाता है। Auto_ptr (...) को चारों ओर रखना आसान है। – lothar

8

आप

auto_ptr<Table> table = auto_ptr<Table>(db->query("select * from t")); 

auto_ptr उपयोग करने के लिए यह टेम्पलेट प्रकार है के लिए एक असाइनमेंट ऑपरेटर को परिभाषित नहीं करता की जरूरत है:

यहाँ मेरी auto_ptr के निर्माता (एसजीआई एसटीएल से) है। एकमात्र अनुमत असाइनमेंट किसी अन्य auto_ptr से है (और यह सूचक से कन्स्ट्रक्टर स्पष्ट है)। Auto_ptr के आकस्मिक दुरुपयोग की रक्षा के लिए यह किया जाता है, क्योंकि auto_ptr स्मृति के स्वामित्व को मानता है।

// initialize using constructor 
auto_ptr<Table> table(db->query("select * from t1")); 
... 
// new query using assignment 
table = auto_ptr<Table>(db->query("select * from t2")); 
... 
// another query using assignment 
table = auto_ptr<Table>(db->query("select * from t3")); 
+1

क्यों नहीं 'auto_ptr

तालिका (db-> प्रश्न (" टी से चयन * "));'? – avakar

+0

वैसे उसने सोचा कि आप स्वयं (उसके प्रश्न देखें)। और जब भी आप एक से अधिक प्रश्न पूछते हैं तो असाइन फ़ॉर्म आवश्यक है :-) – lothar

+0

मेरी इच्छा है कि टिप्पणियां संपादित करने का कोई तरीका हो। uou - हानिकारक तेज़ टाइपिंग ;-) – lothar

2

क्या लोथर को जोड़ना ने कहा: auto_ptr निर्माता explicit कीवर्ड के साथ घोषित किया जाता है, इसलिए आप एक कच्चे सूचक से auto_ptr बनाने के लिए एक व्याख्या कास्ट का उपयोग करने की आवश्यकता है। (explicit की शुरूआत से पहले, अंतर्निहित कास्टिंग कई नए और अनुभवी) सी ++ डेवलपर का झुकाव था।)

5

निर्माता को स्पष्ट के रूप में घोषित किया गया है, जिसका अर्थ है कि इसका उपयोग अंतर्निहित प्रकार के कास्टिंग के लिए नहीं किया जाएगा। Auto_ptr में लागू रूपांतरण आसानी से अवांछित परिस्थितियों का कारण बन सकता है क्योंकि auto_ptr पॉइंटर का स्वामित्व ले रहा है।

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

void fun(std::auto_ptr<Foo> foo) // Assume implicit conversion is allowed. 
{ 
    // do stuff with foo 
} 

Foo *foo = new Foo(); 

f(foo); // Normally this isn't allowed. 

foo->bar(); // Oops 
संबंधित मुद्दे