2011-12-31 10 views
8

नीचे दिए गए कोड को देखें - मैं एक वेक्टर में एक कॉन्स ऑब्जेक्ट डालने की कोशिश कर रहा हूं। मुझे पता है कि जवाब है "एसटीएल कंटेनरों को ऑब्जेक्ट्स को असाइन करने योग्य और कॉपी करने योग्य की आवश्यकता होती है", लेकिन, मानक का हवाला देते हुए, क्या कोई यह समझा सकता है कि ऐसा करने में समस्या क्या है? मुझे समझ में नहीं आ रहा है कि इस तरह की एक वर्ग की प्रतिलिपि क्यों नहीं बनाई जा सकती (इसके अलावा सी ++ इसे अनुमति नहीं देता है)।आप एक एसटीएल कंटेनर में एक कॉन्स ऑब्जेक्ट क्यों नहीं डाल सकते?

यह सब एक मूल्य संग्रहीत है जिसे बदलने की अनुमति नहीं है - इसे वेक्टर में क्यों नहीं डाला जा सकता है बस इन वस्तुओं में से एक बनाते हैं?

#include <vector> 

// Attempt 1 
// /home/doriad/Test/Test.cxx:3:8: error: non-static const member ‘const int MyClass::x’, can’t use default assignment operator 

// struct MyClass 
// { 
// int const x; 
// MyClass(int x): x(x) {} 
// }; 
// 
// int main() 
// { 
// std::vector<MyClass> vec; 
// vec.push_back(MyClass(3)); 
// return 0; 
// } 

// Attempt 2 
// /home/doriad/Test/Test.cxx:28:23: error: assignment of read-only member ‘MyClass::x’ 
struct MyClass 
{ 
    int const x; 
    MyClass(int x): x(x) {} 
    MyClass& operator= (const MyClass& other) 
    { 
    if (this != &other) 
    { 
     this->x = other.x; 
    } 

    return *this; 
    } 
}; 

int main() 
{ 
    std::vector<MyClass> vec; 
    vec.push_back(MyClass(3)); 
    return 0; 
} 

संपादित करें:

यह std :: सेट और std :: सूची के साथ ऐसा करना संभव है। मुझे लगता है कि यह std :: वेक्टर में सॉर्ट() फ़ंक्शन है जो असाइनमेंट का उपयोग करता है। यह यूबी सही नहीं है?

#include <set> 

// Attempt 1 
struct MyClass 
{ 
    int const x; 
    MyClass(int x): x(x) {} 
    bool operator< (const MyClass &other) const; 
}; 

bool MyClass::operator<(const MyClass &other) const 
{ 
    if(this->x < other.x) 
    { 
    return true; 
    } 
    else if (other.x < this->x) 
    { 
    return false; 
    } 

} 


int main() 
{ 
    std::set<MyClass> container; 
    container.insert(MyClass(3)); 
    return 0; 
} 
+0

सेमी से संबंधित: http://stackoverflow.com/questions/2759350/embarassing-c-question-regarding-const/2759426#2759426 – cHao

+0

कृपया std :: vector के बजाय std :: set का उपयोग करके मेरा संपादन देखें। यह ठीक है? –

+0

@ डेविड: सी ++ 03 में, 'std :: set <>' का उपयोग करके, अभी भी बीमार है - §23.1/3 जनादेश देता है कि तत्व प्रकार प्रतिलिपि बनाने योग्य _and_ असाइन करने योग्य होना चाहिए। सी ++ 11 में, आपका कोड अच्छी तरह से गठित है, लेकिन आपका 'std :: set <> 'उदाहरण असाइन करने योग्य नहीं होगा क्योंकि' MyClass' असाइन करने योग्य नहीं है। (इसके अलावा, केवल अर्ध-संबंधित: आपका 'ऑपरेटर <'कार्यान्वयन टूट गया है, क्योंकि यह' यह-> x == अन्य.एक्स') कोई मूल्य वापस नहीं करेगा। – ildjarn

उत्तर

6

EDIT2: सी ++ 11 मानक राज्यों (काम करने के लिए नहीं है कि सामान का एक गुच्छा निकाला जा रहा है) कि vector और deque के लिए insert विधि (और उस बात के लिए push_back के डिफ़ॉल्ट कार्यान्वयन) की आवश्यकता है मान प्रकार CopyAssignable हो सकता है, यानी, मूल्य समर्थन करता है:

t= v; 

वर्ग और const सदस्यों के साथ structs, डिफ़ॉल्ट रूप से नहीं CopyAssignable हैं तो आप क्या करना काम नहीं करेगा चाहते हैं।

यह दस्तावेज़ (n3173) में विभिन्न कंटेनर आवश्यकताओं के लिए एक स्पष्टीकरण है।

+2

एमएसएन: तो मुझे इसे काम करने के लिए क्या करना है? इसने मुझे असाइनमेंट ऑपरेटर को लागू करने के लिए मजबूर किया, लेकिन मैं असाइनमेंट नहीं कर सकता क्योंकि यह स्थिर है! –

+1

@ डेविड: बस कॉन्स्ट डेटा सदस्यों से बचें - यदि आपकी कक्षा उचित कॉन्स-सही गेटर्स प्रदान करती है तो वे बेकार हैं। – ildjarn

+2

यह एक हैक जैसा लगता है, न कि "सही" करने के लिए। –

0

जब आप std :: वेक्टर में MyClass टाइप करने का ऑब्जेक्ट रखते हैं, तो वेक्टर ऑब्जेक्ट की एक प्रतिलिपि भंडारण के लिए बना देगा, न कि उस वस्तु को जिसे आपने पास किया था।

+1

निश्चित रूप से, यह समझ में आता है। लेकिन यह किसी ऑब्जेक्ट को कॉन्स वैल्यू के साथ क्यों कॉपी नहीं कर सकता है? यह सिर्फ एक ही कॉब्जेक्ट मूल्य के साथ एक नई वस्तु बनाने में सक्षम होना चाहिए, नहीं? –

+0

@ डेविड: निश्चित रूप से, लेकिन आप अभी भी 'असाइन करने योग्य' आवश्यकता को याद कर रहे हैं। – ildjarn

1

एक संभावित समाधान वेक्टर में ऑब्जेक्ट्स को पॉइंटर्स स्टोर करना होगा, क्योंकि पॉइंटर्स असाइन करने योग्य और प्रतिलिपि बनाने योग्य हैं।

एक अन्य संभावित समाधान स्थिरांक कीवर्ड के बिना एक्स की घोषणा, लेकिन सुनिश्चित करें कि यह कैप्सूलीकरण के माध्यम से बदला नहीं जा सकता होगा (यानी आप इसे निजी रूप में घोषित करना चाहिए और निर्माता के बाहर कहीं से भी संशोधित नहीं करते हैं) ..

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