2011-12-11 5 views
11

मान लीजिए कि मैंकॉन्स सदस्यों के साथ structs के वेक्टर?

#include <string> 
#include <vector> 
using namespace std; 

struct Student 
{ 
    const string name; 
    int grade; 
    Student(const string &name) : name(name) { } 
}; 

मैं कैसे, फिर, छात्रों के एक वेक्टर रहते हो करते हैं?

int main() 
{ 
    vector<Student> v; 

    // error C2582: 'operator =' function is unavailable in 'Student' 
    v.push_back(Student("john")); 
} 

वहाँ भी यह करने के लिए एक रास्ता है, या मैं बजाय ढेर पर सभी छात्रों को आवंटित करना चाहिए, और एक सूचक की दुकान उनमें से प्रत्येक के लिए?

+0

यह वीसी 2010 के साथ संकलित और लिंक करने लगता है। क्या आप अपने पर्यावरण के बारे में अधिक जानकारी प्रदान कर सकते हैं? क्या यह एक पूर्ण परीक्षण केस है जो संकलन विफलता को पुन: उत्पन्न करता है? – DRH

+0

@DRH: मैं वीसी 2008 पर हूं, क्षमा करें। और हाँ, यह पूरा परीक्षण मामला है। – Mehrdad

+0

जबकि अन्य परिचालनों के लिए आपको असाइनमेंट ऑपरेटर की आवश्यकता होगी, मैं किसी भी संभावित कारणों के बारे में नहीं सोच सकता कि क्यों 'push_back' की आवश्यकता होगी ... फिर, यह हो सकता है कि कार्यान्वयन' असाइन करने योग्य 'आवश्यकता की जांच करे। –

उत्तर

7

आप नहीं कर सकते। आपका प्रकार मानक कंटेनर के लिए "असाइन करने योग्य" आवश्यकता का उल्लंघन करता है।

आईएसओ/आईईसी 14882: 2003 23.1 [lib.container.requirements]/3:

इन घटकों में संग्रहीत CopyConstructible प्रकार (20.1.3) की आवश्यकताओं को पूरा करना होगा वस्तुओं के प्रकार, और Assignable प्रकार की अतिरिक्त आवश्यकताओं।

तालिका से 64 (Assignable आवश्यकताओं):

तालिका 64 में, T कंटेनर का दृष्टांत के लिए इस्तेमाल किया प्रकार है, tT के एक मूल्य है, और u (संभवतः const के एक मूल्य है) T

अभिव्यक्ति: t = u; वापसी का प्रकार: T; बाद हालत: tu

सिद्धांत रूप में करने के लिए बराबर है, एक std::vector बराबर विनाश करने के लिए चुन सकते हैं और सभी मामलों में निर्माण नकल कर सकता है, लेकिन यह है कि अनुबंध है कि चुना गया है नहीं है। यदि पुनर्वितरण की आवश्यकता नहीं है, तो vector::operator= और vector::assign जैसी चीज़ों के लिए निहित प्रकार के असाइनमेंट ऑपरेटर का उपयोग करना अधिक कुशल हो सकता है।

+0

ओह हुह ... तो अगर मुझे कुछ भी असाइन नहीं किया जाता है तो भी इसे असाइन करने योग्य होना चाहिए? उसे नहीं पता था। – Mehrdad

+0

@ फिलिप: वास्तव में, वेक्टर पुन: आवंटित होने पर कुछ भी निर्दिष्ट नहीं करता है। यह आम तौर पर केवल नई प्रतिलिपि बनाता है- या स्थानांतरित करता है और फिर पुराने को हटा देता है। –

+0

हम्म ... यद्यपि 'वेक्टर' कॉपी असाइनमेंट क्यों करता है? क्या यह 'ऑपरेटर =' का उपयोग करने के बजाय निर्माण + विनाश की प्रतिलिपि नहीं कर सकता है? – Mehrdad

8

सरल उत्तर है: आप नहीं कर सकते। यदि आपके पास const सदस्य चर हैं, तो संकलक डिफ़ॉल्ट प्रति-असाइनमेंट ऑपरेटर की आपूर्ति नहीं कर सकता है। हालांकि, std::vector के कई संचालन कार्य करने की आवश्यकता प्रदान करते हैं, और इसलिए एक (सार्वजनिक) कॉपी-असाइनमेंट ऑपरेटर की आवश्यकता होती है।

आपके विकल्प हैं:

  1. name गैर const करें।
  2. अपना खुद का प्रति-कार्य ऑपरेटर लिखें, और const सदस्य "प्रतिलिपि" से निपटने के तरीके के बारे में सोचें।
1

वैक्टरों के तत्व प्रति-असाइन करने योग्य होना चाहिए, जो आपके Student संरचना const सदस्य की वजह से नहीं है। const string name के बजाय बस string name का उपयोग करें। जब तक आपके पास कोई विशिष्ट आवश्यकता न हो, कक्षाओं में निरंतर सदस्य शायद ही कभी उपयोगी होते हैं। यदि आप सदस्य को परिवर्तनों को रोकना चाहते हैं, तो इसे निजी बनाएं और सार्वजनिक गेटर फ़ंक्शन जोड़ें।

3

vector अक्सर तत्वों को चारों ओर स्थानांतरित करने की आवश्यकता होती है।जब भी आप push_back() पर कॉल करते हैं तो वेक्टर को बढ़ने की आवश्यकता होती है, यह स्मृति को स्वयं को संगत रखने के लिए स्मृति को पुन: आवंटित करता है, और सभी मौजूदा तत्वों को नई जगह में प्रतिलिपि बनाता है। अगर आप insert() या remove() तत्वों को पर स्थानांतरित करना चाहते हैं तो भी स्थानांतरित किया जाना चाहिए। vector के लिए यह सब करने में सक्षम होने के लिए तत्वों को कॉपी-असाइन करने योग्य होना चाहिए, जिसका अर्थ है कि वेक्टर में आपके द्वारा संग्रहीत प्रकार में असाइनमेंट ऑपरेटर परिभाषित होना चाहिए।

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

तो, आपके मामले में, समस्या const string name है। यह संकलक को operator=() उत्पन्न करने से रोकता है, जो बदले में vector संकलन से रोकता है, भले ही आप वास्तव में अपने तत्वों पर असाइनमेंट का उपयोग न करें।

एक समाधान name गैर-कॉन्स बनाने के लिए है। दूसरा अपना खुद का Student::operator=() लिखना है, किसी भी तरह से यह समझ में आता है। तीसरा तरीका है, जैसा कि आपने बताया है, ऑब्जेक्ट्स के वेक्टर की बजाय पॉइंटर्स के वेक्टर का उपयोग करने के लिए। लेकिन फिर आपको उनके आवंटन और डी-आवंटन को संभालना होगा।

पीएस दूसरा मामला जब संकलक operator= उत्पन्न नहीं कर सकता है तब आपकी कक्षा में ऐसे सदस्य होते हैं जो संदर्भ हैं।