2012-10-16 16 views
5

में असाइन करने योग्य ऑब्जेक्ट्स का उपयोग करें, मैं std::vector में ऑब्जेक्ट्स की एक सूची स्टोर करना चाहता हूं, लेकिन ऑब्जेक्ट्स में एक संदर्भ होता है और इसे असाइन नहीं किया जा सकता है। हालांकि, मैं ऑब्जेक्ट की प्रतिलिपि बना सकता हूं।सी ++ वेक्टर

एकमात्र विकल्प मैं सोच सकता हूं कि ऑब्जेक्ट्स को लपेटने के लिए पॉइंटर्स का उपयोग करना और पॉइंटर्स को फिर से निर्दिष्ट करने के लिए संशोधित करना है, लेकिन इसके लिए सिंटैक्स पठनीयता को कम कर देगा, खासकर जब इटरेटर का उपयोग करते हैं, और मैं एक पसंद करूंगा वैकल्पिक।

काम नहीं करता:

std::vector<MyObject> myVector; 
//fill the vector 
//... 
myVector[1] = object1; 

स्मार्ट संकेत दिए गए बलिदान पठनीयता:

std::vector<std::unique_ptr<MyObject>> ptrVector; 
//fill the vector 
//... 
ptrVector[1] = std::unique_ptr<MyObject>(new MyObject(object1)); 

वहाँ किसी भी अन्य तरीकों एक std::vector में unassignable वस्तुओं का उपयोग करने के हैं?

+0

सी ++ 11 हैं मान लिया जाये कि, का उपयोग करते हुए 'std :: पारंपरिक संदर्भों के बजाय reference_wrapper' होना एक समाधान? – jogojapan

+0

मुझे नहीं लगता कि आपको कोड की अंतिम पंक्ति में 'std :: move' की आवश्यकता है, क्योंकि' std :: unique_ptr (...) 'एक रावल्यू है। –

+0

@ डेविडरोद्रिगुएज़-ड्राईबीस ओह हाँ, इस सवाल में तय किया गया है। –

उत्तर

2

यह आपके प्रश्न का सीधा जवाब नहीं है क्योंकि मैं std::vector के प्रतिस्थापन की पेशकश नहीं कर सकता, या इसका उपयोग करने का एक अलग तरीका है जो आपको जो करने की आवश्यकता है उसे करने की अनुमति देता है।

हालांकि, यदि MyObject की परिभाषा को संशोधित करना संभव है, तो यह इसे बदलने का विकल्प हो सकता है ताकि यह पारंपरिक संदर्भों के बजाय std::reference_wrapper का उपयोग कर सके। यह MyObject असाइन करने योग्य होने की अनुमति देगा।

उदाहरण:

#include <vector> 
#include <functional> 
#include <iostream> 

struct MyObject 
{ 
    //int &_i; 
    std::reference_wrapper<int> _i; 
    MyObject(int &i):_i(i) {} 
}; 


int main() { 
    std::vector<MyObject> vec; 
    int i1 = 3; 
    int i2 = 4; 
    MyObject c1(i1); 
    MyObject c2(i2); 

    /* Storing object. */ 
    vec.push_back(c1); 

    /* Assigning to it. */ 
    vec[0] = c2; 

    /* Confirming that it's the correct object now. */ 
    for (const MyObject &it : vec) 
    std::cout << it._i << std::endl; 

    /* Modifying the value of its internal reference. */ 
    vec[0]._i.get() = 5; 
    /* Confirming that the original int changed value indeed. */ 
    std::cout << "i2 == " << i2 << std::endl; 

    return 0; 
} 

चेतावनी: मौजूदा कोड पहले से ही संदर्भ सदस्य के लिए सीधी कार्य हो सकती है (अर्थात सदस्य उपरोक्त कोड में _i कहा जाता है)। उन असाइनमेंट का उद्देश्य उस ऑब्जेक्ट के मान को बदलने का था जिसका संदर्भ संदर्भित करता है। std::reference_wrapper के साथ संदर्भ को प्रतिस्थापित करते समय, सभी प्रत्यक्ष असाइनमेंट _i = x को _i.get() = x के साथ प्रतिस्थापित किया जाना चाहिए, अन्यथा कार्यक्रम के अर्थशास्त्र पूरी तरह से बदल जाएंगे।

(संपादित करें) यदि संदर्भ संदर्भ संदर्भ हैं const T&, std::reference_wrapper<const T> का उपयोग किया जा सकता है। ऊपर के उदाहरण का उपयोग करना, MyObject की परिभाषा तो यह करने के लिए परिवर्तन:

struct MyObject 
{ 
    std::reference_wrapper<const int> _i; 
    MyObject(const int &i):_i(i) {} 
}; 
+0

मुझे अभी एहसास हुआ कि ऑब्जेक्ट में 'कॉन्स्ट' संदर्भ है, इसलिए रैपर के संदर्भों को बदलने से यहां कोई मदद नहीं होगी। मैंने परिवर्तन को दर्शाने के लिए अपना प्रश्न संपादित कर लिया है। –

+0

आप उस मामले में 'std :: context_wrapper ' (और जिस प्रकार आप उपयोग कर रहे हैं उसके साथ 'int' को प्रतिस्थापित करें) का उपयोग कर सकते हैं। – jogojapan

+0

ओह, हाहा, जब मैं इसका परीक्षण कर रहा था तो मैंने 'const std :: context_wrapper ' का उपयोग किया। मैंने सवाल वापस कर दिया है। आपकी सभी मदद का धन्यवाद! –

0

क्यों "MyObject" असाइन करने योग्य नहीं है? आप ऑपरेटर "=" को ओवरराइड कर सकते हैं, इस प्रकार "myVector [1] = object1" काम करने योग्य होगा।

+1

क्योंकि 'MyObject' में सदस्य के रूप में संदर्भ होता है। – jogojapan