2012-04-18 14 views
11

मैं इसे डबल करने के लिए मौजूदा vector तत्व की एक प्रति सम्मिलित करने का प्रयास कर रहा हूं। निम्नलिखित कोड पिछले संस्करणों में काम किया लेकिन दृश्य स्टूडियो में विफल रहता है 2010.वेक्टर में डुप्लिकेट तत्व कैसे डालें?

#include <iostream> 
#include <vector> 

using namespace std; 

int main(int argc, char* argv[]) 
{ 
    vector<int> test; 
    test.push_back(1); 
    test.push_back(2); 
    test.insert(test.begin(), test[0]); 
    cout << test[0] << " " << test[1] << " " << test[2] << endl; 
    return 0; 
} 

आउटपुट -17891602 1 2 है, उम्मीद 1 1 2

मुझे पता चला है कि यह क्यों हो रहा है - वेक्टर को फिर से आवंटित किया जा रहा है, और प्रविष्टि बिंदु पर कॉपी करने से पहले संदर्भ अमान्य हो जाता है। पुराने विजुअल स्टूडियो ने स्पष्ट रूप से एक अलग क्रम में चीजें की, इस प्रकार यह साबित कर दिया कि अपरिभाषित व्यवहार का एक संभावित परिणाम सही ढंग से काम करना है और यह भी साबित करना है कि ऐसा कुछ भी नहीं है जिस पर आपको भरोसा करना चाहिए।

मैं इस समस्या को ठीक करने के दो अलग-अलग तरीकों से आया हूं।

template<typename T> 
T make_copy(const T & original) 
{ 
    return original; 
} 

    test.insert(test.begin(), make_copy(test[0])); 

हालांकि:

test.reserve(test.size() + 1); 
    test.insert(test.begin(), test[0]); 

अन्य ताकि शेष संदर्भ पर कोई निर्भरता मान्य है संदर्भ से प्रतिलिपि बनाने के लिए है: एक reserve उपयोग करने के लिए सुनिश्चित करें कि कोई पुनः आबंटन होता है बनाने के लिए है दोनों काम, न ही एक प्राकृतिक समाधान की तरह लगता है। क्या मुझे कुछ याद आ रही है?

+0

बीटीडब्ल्यू वीसी 11 देव पूर्वावलोकन पहले उदाहरण के लिए '1 1 2' देता है। –

+0

@ जेसे, जो मुझे आश्चर्य नहीं करता है। 'डालने' के रावल्यू अधिभार का चयन किया जा रहा था जो कि एक बग की तरह दिखता है जिसे वे तय कर सकते हैं। कोड उस अधिभार के बीच पूरी तरह से अलग है और वह जो कॉन्स्ट संदर्भ लेता है। –

+0

int काम करने के लिए कास्टिंग करता है? –

उत्तर

1

मेरा मानना ​​है कि यह परिभाषित व्यवहार है। 2011 सी ++ मानक के §23.2.3 में, तालिका 100 अनुक्रम कंटेनर आवश्यकताओं को सूचीबद्ध करता है और इस मामले के लिए एक प्रविष्टि है। यह उदाहरण अभिव्यक्ति

a.insert(p,t) 

जहां a जो एक दृश्य कंटेनर प्रकार T के तत्वों से युक्त प्रकार है X के एक मूल्य है देता है, pa करने के लिए एक स्थिरांक इटरेटर है, और t एक lvalue या प्रकार X::value_type की स्थिरांक rvalue है , यानी T

इस अभिव्यक्ति के लिए दावा है:

आवश्यक है:TX में CopyInsertable होगा। vector और deque, T के लिए भी CopyAssignable होगा।
प्रभाव:p से पहले t की प्रतिलिपि डालें।

टिप्पणी:: पुनः आबंटन का कारण बनता है, तो नया आकार वर्ष क्षमता से अधिक है

केवल प्रासंगिक वेक्टर विशिष्ट बोली मैं मिल सकता है §23.3.6.5 अनुच्छेद 1 में है। यदि कोई पुनर्वितरण नहीं होता है, तो सम्मिलन बिंदु से पहले सभी पुनरावृत्तियों और संदर्भ मान्य रहते हैं।

हालांकि यह वेक्टर को फिर से आवंटित करने का उल्लेख करता है, यह अनुक्रम कंटेनर पर insert के लिए पिछली आवश्यकताओं के लिए अपवाद नहीं करता है।

इस मुद्दे के आसपास काम करने के लिए, मैं तत्व की एक प्रति बनाने और उस प्रति को सम्मिलित करने के लिए @ एडचम के सुझाव से सहमत हूं।

+0

मुझे आपके विवरण में कुछ भी दिखाई नहीं देता है जो उस मामले को कहता है जहां' t' 'a' के सदस्य का संदर्भ है। –

4

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

#include <iostream> 
#include <vector> 

using namespace std; 

int main(int argc, char* argv[]) 
{ 
    vector<int> test; 
    test.push_back(1); 
    test.push_back(2); 
    test.insert(test.begin(), int(test[0])); 
    cout << test[0] << " " << test[1] << " " << test[2] << endl; 
    return 0; 
} 
+0

यह सिर्फ एक परीक्षण मामला है। मेरे वास्तविक कोड में ऐसे तत्व होते हैं जो एक int से अधिक जटिल होते हैं, और अस्थायी के लिए निर्माता केवल बदसूरत हो जाता है। हालांकि अच्छा सुझाव है। –

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