2013-02-27 33 views
7

मैं ऐसे प्रोग्राम के साथ काम कर रहा हूं जो std::vector का उपयोग करता है। इसके अलावा बहुत सारे आवंटन/विलोपन होते हैं, उनमें से अरबों, और मैं जितना संभव हो उतना से बचने की कोशिश कर रहा हूं। चूंकि मैं सी ++ के लिए अपेक्षाकृत नया हूं, मेरे पास वेक्टर का उपयोग करते समय आवंटन के संबंध में कुछ प्रश्न हैं (उदाहरण के लिए तत्व जोड़ते समय)। मैं Win7 64-बिट मशीन पर हूं, प्रोग्राम 32-बिट है और मैं MinGW-compilers के वर्तमान संस्करण का उपयोग कर रहा हूं।एक वेक्टर कॉपी कब किया जाता है, एक संदर्भ कब पास किया जाता है?

मुझे पता करना चाहते हैं, क्या निम्नलिखित मामलों में होता है, यानी वेक्टर नकल की जाती है, तो, एक संदर्भ के रूप पारित कर दिया, ...

1.

std::vector<T> fillVector() { 
    std::vector<T> returnVector; 
    ... 
    return returnVector; 
} 

std::vector<T> myVector = fillVector(); 

2.

std::vector<T>& fillVector() { 
    std::vector<T>* returnVector = new std::vector<T>; 
    ... 
    return (*returnVector); 
} 

std::vector<T> myVector = fillVector(); 

3.

std::vector<T>* fillVector() { 
    std::vector<T>* returnVector = new std::vector<T>; 
    ... 
    return returnVector; 
} 

std::vector<T>* myVector = fillVector(); 

और निम्न, विभिन्न कार्यों:

4.

std::vector<T> myVector1; 
... (myVector1 being filled) 
std::vector<T> myVector = myVector1; 

5.

std::vector<T>* myVector1 = new std::vector<T>; 
... (myVector1 being filled) 
std::vector<T> myVector = (*myVector1); 

मान लिया जाये कि मैं myFunction wouldn में myVector में myFunction/परिवर्तन में तर्क को बदलने के लिए नहीं करना चाहते हैं बाकी कार्यक्रम को चोट नहीं पहुंचा:

6.

void myFunction(std::vector<T> myParam) { 
    ... 
} 

std::vector<T> myVector; 
... (myVector being filled) 
myFunction(myVector); 

7.

void myFunction(std::vector<T>& myParam) { 
    ... 
} 

std::vector<T> myVector; 
... (myVector being filled) 
myFunction(myVector); 

तो मेरी समझ सही है, तो सबसे तेजी से विकल्प (गुजर संदर्भ अर्थ प्रतियां बनाने और उन्हें पारित करने के बजाय) होगा 2/3, 5 और 7 कृपया मुझे अगर सही कर मैं गलत हूँ!

+1

सबसे तेज़ और साफ विकल्प 1 है। – juanchopanza

उत्तर

1

सबसे तेज़ और सबसे बेवकूफ विकल्प 1 है। दोनों प्रतियां (returnVector से मूल्य वापस करने के लिए और वापसी मूल्य से myVector) लगभग निश्चित रूप से आपके कंपाइलर द्वारा elided होगा। कॉपी एलिजन एक अनुकूलन है कि संकलक ऐसा कर सकता है जिसमें किसी भी अनावश्यक प्रतियों को हटाया जा सके। यहां, दोनों प्रतियां अनावश्यक हैं और std::vector सीधे myVector के स्थान पर बनाई जाएगी।

असल में, यदि आप अपने कंपाइलर के साथ प्रतिलिपि अनुकूलन को अक्षम करते हैं, तो सी ++ 11 में दोनों प्रतियां वास्तव में चलती रहेंगी। std::vector को स्थानांतरित करने के लिए कुछ असाइनमेंट की आवश्यकता है और यह बहुत तेज़ है। पहले को एक विशेष नियम द्वारा एक कदम माना जाता है और दूसरा एक कदम है क्योंकि अभिव्यक्ति fillVector() एक रैल्यू अभिव्यक्ति है।

+0

जो मैंने किए गए कुछ प्रयोगों को समझाया, जो वास्तव में मुझे समझ में नहीं आया। – MrWayne

7

1.

std::vector<T> fillVector() { 
    std::vector<T> returnVector; 
    ... 
    return returnVector; 
} 

std::vector<T> myVector = fillVector(); 

यह ठीक है। vectorमूल्य द्वारा वापस कर दिया गया है, लेकिन कॉपी कन्स्ट्रक्टर को कॉल (नामांकित) रिटर्न वैल्यू ऑप्टिमाइज़ेशन के तहत अधिकांश कंपाइलर्स (कम से कम अनुकूलन चालू होने पर) द्वारा elided है।

इसके अलावा, सी ++ 11 के साथ, सेमेन्टिक्स को स्थानांतरित करें यह सुनिश्चित करता है कि प्रतिलिपि कन्स्ट्रक्टर की बजाय चालक कन्स्ट्रक्टर को बुलाया जाता है, जो एक महंगी प्रति उत्पन्न किए बिना लौट वेक्टर की गड़बड़ी चुरा लेगा।

2.

std::vector<T>& fillVector() { 
    std::vector<T>* returnVector = new std::vector<T>; 
    ... 
    return (*returnVector); 
} 

std::vector<T> myVector = fillVector(); 

ऐसा मत करो। गतिशील आवंटन के अनावश्यक ओवरहेड, साथ ही यह याद रखने का बोझ कि आपको लौटे ऑब्जेक्ट को हटाना होगा। नियमित स्मृति प्रबंधन से बचें और पसंद करते हैं इसके बाद के संस्करण के रूप में 1.

3.

std::vector<T>* fillVector() { 
    std::vector<T>* returnVector = new std::vector<T>; 
    ... 
    return returnVector; 
} 

std::vector<T>* myVector = fillVector(); 

ही। मैन्युअल मेमोरी प्रबंधन से बचें।

4.

std::vector<T> myVector1; 
... (myVector1 being filled) 
std::vector<T> myVector = myVector1; 

यह एक धारणात्मक अलग ऑपरेशन है। प्रतिलिपि बनाने के लिए यहां चाहते हैं, और ऐसा लगता है कि आप इसे सही कर रहे हैं। सी ++ 11 में आप std::vector<T> myVector = std::move(myVector1) का उपयोग करना चाहेंगे यदि आपको इसकी आवश्यकता है तो स्थानांतरणmyVector1 की सामग्री को कॉपी करने के बजाय।

5.

std::vector<T>* myVector1 = new std::vector<T>; 
... (myVector1 being filled) 
std::vector<T> myVector = (*myVector1); 
ऊपर के रूप में एक ही

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

6.

void myFunction(std::vector<T> myParam) { 
    ... 
} 

std::vector<T> myVector; 
... (myVector being filled) 
myFunction(myVector); 

यहाँ आप मान द्वारा myVector गुजर रहे हैं। चाहे यह अनुकूलित किया जा सके या नहीं, myFunction पर निर्भर करता है कि इसके तर्क के साथ क्या किया जाए: क्या यह इसे बदल देगा? यदि हां, तो क्या आप फ़ंक्शन से लौटने के बाद इन परिवर्तनों को दिखाना चाहते हैं? यदि हां, तो मूल्य से गुजरना सही है और इसे अनुकूलित करने का कोई तरीका नहीं है जब तक कि आप myVector ऑब्जेक्ट की सवारी करना चाहते हैं: उस स्थिति में, C++ 11 में आप को फ़ंक्शन पर पास करते समय इसे स्थानांतरित कर सकते हैं । यह एक महंगी, अनावश्यक प्रतिलिपि से बच जाएगा।

7.

void myFunction(std::vector<T>& myParam) { 
    ... 
} 

std::vector<T> myVector; 
... (myVector being filled) 
myFunction(myVector); 

इस संदर्भ द्वारा पारित करेंगे, और यह ठीक जब तक यह समारोह से लौटने के बाद myVector पर myFunction के साइड इफेक्ट को देखने के लिए ठीक है। इसे सामान्य रूप से नहीं बताया जा सकता है कि यह सही है या नहीं, यह आपके आवेदन के विशेष तर्क पर निर्भर करता है।

+0

विस्तृत उत्तर के लिए धन्यवाद। मैंने अपनी पहली पोस्ट 6 और 7 के बारे में संपादित की है: आइए मान लें कि 'myFectction' के अंदर 'myVector' में किए गए परिवर्तन शेष कार्यक्रम को नुकसान नहीं पहुंचाएंगे, फिर संदर्भ से गुजरना निश्चित रूप से तेज़ होगा, है ना? – MrWayne

+0

@MrWayne: उस मामले में, हाँ। वह तेज़ होगा। यह एकमात्र सही तरीका भी हो सकता है यदि आपने अपना "बदलना नहीं" में बदल दिया है "इसे देखा जाना चाहिए" –

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