2016-11-17 20 views
7

नीचे के सदस्य के रूप unique_ptr साथ वर्ग शरीर में घोषित कोड की minimalist समस्या है। मेरी आवश्यकता के लिए, मुझे ~B() का शरीर स्पष्ट रूप से परिभाषित करने की आवश्यकता है।संकलक त्रुटि जब नाशक एक ही कक्षा

मैं उसी श्रेणी में unique_ptr सह-विद्यमान के साथ विनाशक के शरीर को कैसे परिभाषित कर सकता हूं?

नोट: कोई लाभ नहीं हुआ प्रतिलिपि & चाल निर्माता की = default संस्करणों को परिभाषित करने की कोशिश की। मेरे असली कोड में, unique_ptr<int>unique_ptr<forward_declared_class> है। SO में इस समस्या का पता नहीं लगा सका, हालांकि मुझे यकीन है कि यह उपस्थित होना चाहिए। डुप्ली के रूप में चिह्नित करने के लिए स्वतंत्र महसूस करें।

+0

घोषित आगे होने से समस्या के लिए प्रासंगिक है - विश्वसनीय रूप से 'हटाएं' को कॉल नहीं कर सकता (यानी एक दृश्य विनाशक के बिना 'std :: default_deleter' को तत्काल नहीं कर सकता)। – milleniumbug

+0

यह प्रश्न देखें http://stackoverflow.com/questions/6012157/is-stdunique-ptrt-required-to-now-the-full-definition-of-t – milleniumbug

+0

m_pB को nullptr असाइन करने का कोई कारण नहीं है। –

उत्तर

5

लगता है की तरह अपने कोड B की आवश्यकता है constructible कॉपी और std::vector के लिए आबंटित की प्रतिलिपि (कम से कम दृश्य ग के लिए ++, जो मैं परीक्षण किया) होने के लिए ।

कॉपी निर्माता और कॉपी assignement ऑपरेटरों केवल हो सकता है = delete क्योंकि std::unique_ptr की (कार्यान्वयन घोषित = default कारण चाहिए समारोह के रूप में अच्छी तरह से हटाए जाने के लिए), और, नाशक को लागू करने से, आप इस कदम निर्माता के डिफ़ॉल्ट कार्यान्वयन को निष्क्रिय और असाइनमेंट ऑपरेटर चलते हैं।

तो आपको स्पष्ट रूप से चाल असाइनमेंट ऑपरेटर घोषित करने की आवश्यकता है। आज़माएं:

#include <memory> 
#include <vector> 

struct B { 
    B() = default; 
    ~B() {} 
    B& operator=(B&&) = default; 
    std::unique_ptr<int> m_pB = nullptr; 
}; 

int main() 
{ 
    std::vector<B> vB; 
    vB.erase(vB.begin()); 
} 
3

आप एक चाल-असाइनमेंट ऑपरेटर घोषित और कार्यान्वित कर सकते हैं, जिसे संकलक पूछता है। बेशक, यह कॉपी असाइनमेंट के बारे में शिकायत करता है, लेकिन आपकी समझ के लिए एक समझदार प्रति असंभव प्रतीत होती है।

शायद, त्रुटि संदेश थोड़ा भ्रामक है क्योंकि std::vector::erase कार्यान्वयन में कोड में _data[i-1] = _data[i] जैसे कुछ शामिल हैं जो हटाए गए आइटमों के स्थान पर वेक्टर तत्वों को पोक करता है। तो कंपाइलर को किसी भी असाइनमेंट ऑपरेटर की आवश्यकता होती है, और हम इसे एक चलती एक प्रदान करते हैं।

उदाहरण के लिए, इस काम करता है ठीक (जीसीसी 4.8.3):

struct B { 
    B() = default; 
    B& operator=(B&& op) { 
    m_pB = std::move(op.m_pB); 
    return *this; 
    } 
    ~B() {}; // no more errors. 
    std::unique_ptr<int> m_pB = nullptr; 
}; 

int main() 
{ 
    std::vector<B> vB; 
    vB.erase(vB.begin()); 
} 
0

वेक्टर कोड एक लाल हेरिंग है।

जब कक्षा यू के पास अद्वितीय_ptr प्रकार का सदस्य होता है, और टी को आगे घोषित किया जाता है, तो विनाशक की परिभाषा सीपीपी फ़ाइल में होनी चाहिए, जब यू अब अधूरा प्रकार नहीं है।

आपके पास ~ यू() होना चाहिए; शीर्षलेख में, और सीपीपी फ़ाइल में यू :: ~ यू() {} या यू :: ~ यू() = डिफ़ॉल्ट है;