2010-01-26 16 views
17

"से कदम" सी ++ 11 में, हम एक दक्षता को बढ़ावा देने std::move का उपयोग करके जब हम ले जाना चाहते हैं (विध्वंस कॉपी) प्राप्त कर सकते हैं एक कंटेनर में महत्व देता है:सी ++ कंटेनर

SomeExpensiveType x = /* ... */; 
vec.push_back(std::move(x)); 

लेकिन मैं नहीं कर सकता दूसरी तरफ जा रहा कुछ भी ढूंढें। stack तरह एडाप्टर के पर

SomeExpensiveType x = vec.back(); // copy! 
vec.pop_back(); // argh 

यह और अधिक अक्सर होता है (कॉपी पॉप): क्या मेरा मतलब है कुछ इस तरह है। इस तरह कुछ ऐसा हो सकता है:

प्रतिलिपि से बचने के लिए? और क्या यह पहले से मौजूद है? मुझे एन 3000 में ऐसा कुछ नहीं मिला।

मुझे एहसास है कि मुझे दर्दनाक रूप से कुछ याद आ रहा है (इसकी अनावश्यकता की तरह), इसलिए मैं "आरयू डम" के लिए तैयार हूं। : 3

+0

क्या निहितार्थ कदम विधि चरों कि क्षेत्र से बाहर जाने पर है? उदाहरण के लिए, यदि मैं कोई ऑब्जेक्ट बनाता हूं, तो उसे सदस्य कंटेनर में जोड़ें, फिर ऑब्जेक्ट स्कोप से बाहर हो जाता है ... चूंकि कोई प्रतिलिपि नहीं बनाई गई थी, क्या सदस्य कंटेनर में ऑब्जेक्ट अभी भी परिभाषित है? – Polaris878

+0

हां, इसे कंटेनर में ले जाया गया था। यदि आप सुनिश्चित नहीं हैं कि वे कैसे काम करते हैं, तो आप रावलू संदर्भों को Google करना चाहेंगे। – GManNickG

+0

मीठा धन्यवाद ... मुझे इसे और अधिक लॉल में खोदना होगा। चेहरे की कीमत पर ऐसा लगता है कि इससे समस्याएं पैदा होंगी। – Polaris878

उत्तर

15

मैं कुल गलत यहाँ हो सकता है, लेकिन आप केवल

SomeExpensiveType x = std::move(vec.back()); vec.pop_back(); 

मान लिया जाये कि SomeExpensiveType एक चाल निर्माता है क्या चाहते हैं नहीं है। (और आपके मामले के लिए स्पष्ट रूप से सच है)

+0

मैंने इसके बारे में सोचा, लेकिन मैं इस तरह के कंटेनर से कुछ ले जाने से सावधान हूं। अब जब मैं इसके बारे में और सोचता हूं, यह पूरी तरह कानूनी लगता है ...: | – GManNickG

+0

हम्म। मुझे यकीन नहीं है कि यह सही है। निश्चित रूप से vec.back() में चलने वाले अर्थशास्त्र होना आवश्यक है, यानी एक और – ScaryAardvark

+0

आपको याद करें, मैंने इसके बारे में कुछ और सोचा है और आप सही हो सकते हैं। – ScaryAardvark

-1

आम तौर पर महंगा प्रकारों के लिए मुझे लगता है कि आप या तो कंटेनर में एक रैपर वर्ग या स्मार्ट पॉइंटर को धक्का देना चाहते हैं। इस तरह आप महंगे प्रतियों से परहेज कर रहे हैं और इसके बजाय केवल स्मार्ट पॉइंटर या रैपर वर्ग की सस्ती प्रतियां कर रहे हैं। यदि आप हाहा चाहते हैं तो आप कच्चे पॉइंटर्स का भी उपयोग कर सकते हैं।

class ExpensiveWrapper 
{ 
public: 
    ExpensiveWrapper(ExpensiveClass* in) { mPtr = in; } 

    // copy constructors here.... 

private: 
    ExpensiveWrapper* mPtr; 

}; 
+3

'विधि' अर्थशास्त्र का एक बिंदु इस विधि से छुटकारा पाने के लिए है। कंटेनर केवल उनकी प्रतिलिपि बनाने के बजाय उनकी सामग्री को 'स्थानांतरित' करेंगे। – GManNickG

4

पूर्णता (और एक सी ++ 1x संकलक के बिना इस प्रश्न पर ठोकर किसी को) एक वैकल्पिक पहले से मौजूद है कि आज के लिए:

SomeExpensiveType x; 
std::swap(x, vec.back()); 
vec.pop_back(); 

यह सिर्फ के लिए मौजूद std::swap की विशेषज्ञता की आवश्यकता है तत्व प्रकार।

+3

स्पष्ट रूप से std :: स्वैप का उपयोग न करें (क्योंकि इसे कई प्रकार के लिए ठीक से विशिष्ट नहीं किया जा सकता है); एक अयोग्य स्वैप कॉल के साथ उपयोग-घोषणा का उपयोग करें। –

+1

@Roger Pate - या एक ही चीज़ प्राप्त करने के लिए 'boost :: swap' का उपयोग करें। –

+0

मैं बूस्ट के बारे में शिकायत करने वाले व्यक्ति के बारे में चिंता करने की बजाय एक पंक्ति टाइप करना चाहता हूं, क्योंकि कोई अनिवार्य रूप से करता है। :) –

4
template<class C> 
auto pop_back(C& c) -> typename std::decay<decltype(c.back())>::type 
{ 
    auto value (std::move(c.back())); 
    c.pop_back(); 
    return value; // also uses move semantics, implicitly 
    // RVO still applies to reduce the two moves to one 
} 
+0

मुझे std :: removal_reference की तुलना में std :: decay अधिक उपयुक्त लगता है। उदाहरण के लिए, यह एक "MyClass" (कॉन्स को हटाने) में "const MyClass &" को बदल देता है। – sellibitze

+0

@ सेलिबिटज़: आप सही हैं, यह अधिक उपयुक्त है; धन्यवाद! –

+0

मैं 100% निश्चित नहीं हूं लेकिन 'टाइपनाम' संभवतः '->' – sellibitze

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