2012-07-20 22 views
17

मान लीजिए मैं निम्नलिखित कोड है:ले जाएँ :: push_back

#include <vector> 
struct A { 
    int a; 
    int x; 
}; 
int main() { 
    using namespace std; 
    A a1; 
    A a2; 
    vector<A> va; 
    va.push_back(a1); 
    va.push_back(move(a2)); 
} 

मुझे पता है कि std :: वेक्टर के तत्वों समीप जमा हो जाती है एक std :: सूची के विपरीत, कर रहा हूँ। उपरोक्त कोड में a2 स्थानांतरित हो गया है लेकिन क्या वास्तव में वेक्टर va पर a2 की कोई प्रतिलिपि नहीं है? va.push_back(a2); और के बीच क्या अंतर है?

+2

आपके मामले में, 'std :: move'ing' a2' बिल्कुल * कुछ नहीं * है, क्योंकि यह एक समतल प्रकार है (यानी, इसका कोई बाहरी डेटा नहीं है) और अभी भी प्रतिलिपि बनायेगा। – Xeo

+0

@cdhowie धन्यवाद। ठीक कर दिया। – ggg

+0

आप पढ़ना चाह सकते हैं [क्या कोई मुझे अर्थात् स्थानांतरित करने के लिए परिचय के लिए व्याख्यान व्याख्या कर सकता है?] (Http://stackoverflow.com/questions/3106110/)। – fredoverflow

उत्तर

26

आपके मामले में, कोई प्रभावी अंतर नहीं है, क्योंकि आप कंपाइलर-प्रदत्त प्रति रचनाकारों का उपयोग कर रहे हैं। चलने वाली वस्तुओं का उपयोग करते समय आपको एक उल्लेखनीय प्रदर्शन अंतर दिखाई देगा, और प्रतिलिपि बनाने के लिए बहुत सारे प्रयास करें। उस स्थिति में, push_back(x) का उपयोग ऑब्जेक्ट की एक प्रति बना देगा, जबकि push_back(move(x))push_back() बताएगा कि यह x की सामग्री को "चोरी" कर सकता है, x को अनुपयोगी और अपरिभाषित स्थिति में छोड़ सकता है।

विचार करें कि क्या आपके पास सूचियों का वेक्टर था (std::vector<std::list<int> >) और आप 100,000 तत्वों वाली एक सूची को धक्का देना चाहते थे। move() के बिना, संपूर्ण सूची संरचना और सभी 100,000 तत्वों की प्रतिलिपि बनाई जाएगी। move() के साथ, कुछ पॉइंटर्स और डेटा के अन्य छोटे बिट्स चारों ओर घूमते हैं, और यह इसके बारे में है। यह बहुत तेज होगा, और कम समग्र स्मृति खपत की आवश्यकता होगी।

+1

क्यों? सी-टोर को स्वचालित रूप से जेनरेट किया जाएगा, ऐसा नहीं? – ForEveR

+6

@ForEveR इससे कोई फ़र्क नहीं पड़ता कि कोई स्वचालित रूप से जेनरेट किया गया है या नहीं, क्योंकि 'ए' संरचना में कोई आवंटन नहीं किया जा सकता है जिसे स्थानांतरित किया जा सकता है। आपके पास केवल दो 'int' है, और चालक कन्स्ट्रक्टर वही काम करेगा जो कॉपी कन्स्ट्रक्टर करेगा: स्रोत ऑब्जेक्ट पर इन ऑब्जेक्ट्स को नए ऑब्जेक्ट में संग्रहीत मान असाइन करें। इस प्रकार के साथ चाल परिदृश्य में अनुकूलन की कोई संभावना नहीं है, क्योंकि यह पहले से ही इष्टतम है जितना इसे प्राप्त हो सकता है। – cdhowie

+0

@cdhowie तो किसी चाल के दौरान हमेशा कुछ कॉपी किया जाएगा? – ggg

14

जब आप va.push_back(a2) संस्करण vector<T>::push_back(const T&) उपयोग करते हैं, के नाम से जाना जाएगा जब आप का उपयोग va.push_back(move(a2)) संस्करण vector<T>::push_back(T&&) बुलाया जाएगा ...

लेकिन आपके मामले में वहाँ कार्यक्षमता के लिए कोई अंतर नहीं है,

के बाद से

15 एक गैर-संघ वर्ग एक्स के लिए अंतर्निहित रूप से परिभाषित प्रतिलिपि/चालक कन्स्ट्रक्टर अपने सदस्यों और सदस्यों की सदस्यवाही प्रतिलिपि/चाल करता है।

अनुच्छेद 12.8 n3337 ड्राफ्ट।

0

मैं कुछ ऐसा नोट करना चाहता हूं जो अन्य उत्तरों खत्म नहीं हुआ हो; यह है कि ?.push_back(move(?)) आपके मामले में ?.push_back(?) से धीमा हो जाएगा (जब आपके पास त्रिकोणीय रूप से कॉपी करने योग्य ऑब्जेक्ट्स हों), क्योंकि चालक को स्थानांतरित करने की आवश्यकता शून्य हो जाती है, जिसे प्रभावी ढंग से आप दो ऑब्जेक्ट्स कॉपी कर रहे हैं।

+0

एक चालक कन्स्ट्रक्टर को स्थानांतरित वस्तु पर कुछ भी करने की आवश्यकता नहीं है। इसे तब तक शून्य करने की आवश्यकता नहीं है जब तक कि पॉइंटर्स नहीं ले जाते हैं जिन्हें शून्य पर रीसेट करने की आवश्यकता होती है। (कंपाइलर से उत्पन्न चालक कन्स्ट्रक्टर स्रोत ऑब्जेक्ट को कंबल-शून्य नहीं जा रहे हैं।) – cdhowie

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