2011-12-23 14 views
32

संभव डुप्लिकेट:
Move semantics == custom swap function obsolete?क्या विशेषज्ञता है std :: स्वैप अब बहिष्कृत है कि हमने अर्थशास्त्र को स्थानांतरित किया है?

यह कैसे std::swap सी ++ 11 में की तरह लग रहा है:

template<typename T> 
void swap(T& x, T& y) 
{ 
    T z = std::move(x); 
    x = std::move(y); 
    y = std::move(z); 
} 

मैं अभी भी अपने स्वयं के प्रकार के लिए std::swap विशेषज्ञ है , या std::swap जितना कुशल हो उतना कुशल होगा, बशर्ते कि मेरी कक्षा परिभाषित करे ओवे कन्स्ट्रक्टर और एक कदम असाइनमेंट ऑपरेटर, ज़ाहिर है?

+0

मैं कहना चाहता हूं कि स्कॉट या हर्ब द्वारा _C++ और Beyond_ पर इसका उल्लेख किया गया था, लेकिन मुझे इसके बारे में कुछ भी नहीं मिल रहा है। –

+2

संबंधित: [semantics == कस्टम स्वैप फ़ंक्शन अप्रचलित ले जाएं?] (Http://stackoverflow.com/questions/6416385/move-semantics- कस्टम-wap- कार्यक्षमता- अप्रचलित) – Xeo

+0

@Xeo: धन्यवाद, मैं पूरी तरह से भूल गया था वह प्रश्न/उत्तर। क्या मुझे लगातार होने के लिए अंक मिलते हैं? :-) मुझे यकीन है कि अन्यथा लाल चेहरे का सामना करना पड़ता! –

उत्तर

30

std::swap की विशेषज्ञता अब वैकल्पिक है, लेकिन नहीं पदावनत है। तर्क प्रदर्शन है।

प्रोटोटाइप कोड के लिए, और शायद अधिक शिपिंग कोड के लिए भी, std::swap बहुत तेज़ होगा। हालांकि यदि आप ऐसी परिस्थिति में हैं जहां आपको अपने कोड से हर छोटी सी चीज की आवश्यकता है, तो एक कस्टम स्वैप लिखना अभी भी एक महत्वपूर्ण प्रदर्शन लाभ हो सकता है।

उस मामले पर विचार करें जहां आपकी कक्षा के पास अनिवार्य रूप से एक मालिक है और आपके चालक कन्स्ट्रक्टर और असाइनमेंट को ले जाना है, उसे केवल एक सूचक से निपटना होगा।प्रत्येक सदस्य के लिए मशीन लोड और स्टोर की गणना करें:

कन्स्ट्रक्टर ले जाएं: 1 लोड और 2 स्टोर्स।

असाइनमेंट ले जाएं: 2 भार और 2 स्टोर।

कस्टम स्वैप: 2 भार और 2 स्टोर।

std::swap 1 चाल निर्माण और 2 चाल असाइनमेंट, या: 5 भार और 6 स्टोर हैं।

एक कस्टम स्वैप संभावित रूप से std::swap से दो या तीन गुना तेज है। हालांकि किसी भी समय आप भार और दुकानों की गिनती करके कुछ की गति को समझने की कोशिश कर रहे हैं, दोनों दुष्ट तेजी से होने जा रहे हैं।

नोट: अपने चाल असाइनमेंट की लागत की गणना करने में, सुनिश्चित करें और ध्यान दें कि आप एक स्थानांतरित मूल्य से आगे बढ़ेंगे (std::swap एल्गोरिदम में)। यह अक्सर एक शाखा की लागत पर, एक deallocation की लागत को अस्वीकार करता है।

+7

क्या कंपाइलर को चाल असाइनमेंट को इनलाइन करने और मृत स्टोर को निकालने के लिए संभव नहीं होना चाहिए? – u0b34a0f6ae

+7

मैं एक कंपाइलर इंजीनियर नहीं हूँ। मुझे लगता है कि यह संभव है, लेकिन मुझे यकीन नहीं है। मैं इस पर निर्भर होने में संकोच करता हूं। दिन के अंत में आपको इसे दोनों तरीकों और परीक्षणों को कोड करना होगा। और यदि आपका परीक्षण इंगित करता है कि 'std :: swap' उतनी तेज़ है, तो परिणाम संकलक/प्लेटफॉर्म पर निर्भर हो सकता है। और यदि आपका एप्लिकेशन किसी प्रदर्शन क्षेत्र में महत्वपूर्ण रूप से 'स्वैप' नहीं करता है, तो शायद आपको कोई परवाह नहीं है कि 'std :: swap' दुष्ट तेज़ जितना धीमा है। –

+1

पार्टी के लिए थोड़ा देर हो रहा है ... लेकिन मुझे एक साधारण संदेह है: मूव असाइनमेंट को 2Loads + 2Stores (मूव कन्स्ट्रक्टर से 1 और लोड) के लिए क्यों जिम्मेदार ठहराया गया है? क्या ऐसा इसलिए है क्योंकि इसे "वापसी * ​​करना" है? या इसे पुन: असाइन करने से पहले मालिक पॉइंटर को "हटाएं" की निहित आवश्यकता के कारण, और इसलिए इसे हटाए गए अभिव्यक्ति में पढ़ना होगा? – abigagli

0

यह आपके प्रकारों पर निर्भर करेगा।

आप इसे x से z तक, y से x तक, z से y तक ले जाएंगे। अंतर्निहित प्रतिनिधित्व के तीन प्रति संचालन (शायद केवल एक सूचक, शायद कुछ और, जो जानता है)

अब आप अपने प्रकार के लिए एक तेज़ स्वैप बना सकते हैं (xor स्वैप चाल, इनलाइन असेंबलर, या शायद std :: अपने अंतर्निहित प्रकारों के लिए स्वैप बस तेज है)।

या शायद आपका कंपाइलर अनुकूलित करने में भी अच्छा है, और अनिवार्य रूप से दोनों मामलों को एक ही निर्देश में अनुकूलित करता है (जैसे एक रजिस्टर में अस्थायी)।

मैं व्यक्तिगत रूप से हमेशा एक स्वैप सदस्य फ़ंक्शन को लागू करता हूं जिसे कई स्थानों से बुलाया जाएगा, जिसमें चाल असाइनमेंट जैसी चीजें शामिल हैं, लेकिन वाईएमएमवी।

0

यह swap() एक चालक कन्स्ट्रक्टर और 2 चाल असाइनमेंट को कॉल करता है। मैं इस कदम निर्माता और असाइनमेंट ऑपरेटर के कार्यान्वयन की परवाह किए बिना लगता है कि एक तरह वर्ग के अपने विशेष प्रकार के और अधिक कुशल swap() लिख सकते हैं,

class X 
{ 
    int * ptr_to_huge_array; 
public: 
// ctors, assgn ops. etc. etc. 

    friend void swap(X& a, X& b) 
    { 
     using std::swap; 
     swap(a.ptr_to_huge_array, b.ptr_to_huge_array); 
    } 
}; 

+0

कॉपी कन्स्ट्रक्टर कहां है? क्या आप एक अधिक कुशल स्वैप का उदाहरण दे सकते हैं? – ronag

+0

@ronag: क्षमा करें, मेरी गलती। –

2

क्या विशेषज्ञता है std :: swap अब बहिष्कृत है कि हमने अर्थशास्त्र को स्थानांतरित किया है?

नहीं। यह सामान्य संस्करण है, लेकिन आप इसे तीसरे स्थान के संचालन को छोड़ने के लिए अनुकूलित कर सकते हैं। मेरी प्राथमिकता है कि मेरी कक्षाओं के लिए std :: स्वैप को अनुकूलित करने के साथ कॉपी & स्वैप मुहावरे को गठबंधन करना है।

इसका मतलब है कि मैं होगा:

class Aaaa 
{ 
public: 
    Aaaa(); // not interesting; defined elsewhere 
    Aaaa(Aaaa&& rvalueRef); // same 
    Aaaa(const Aaaa& ref); // same 
    ~Aaaa(); // same 
    Aaaa& operator=(Aaaa object) // copy&swap 
    { 
     swap(object); 
     return *this; 
    } 
    void swap(Aaaa& other) 
    { 
     std::swap(dataMember1, other.dataMember1); 
     std::swap(dataMember2, other.dataMember2); 
     // ... 
    } 

    // ... 
}; 

namespace std 
{ 
    template<> inline void std::swap(Aaaa& left, Aaaa& right) 
    { left.swap(right); } 
} 
+3

'स्वैप' का उपयोग करने का सही तरीका 'std :: swap' का उपयोग करना है, इसके बाद एक अयोग्य कॉल' swap' 'है। साथ ही, 'std :: swap' को विशेषज्ञता देना बहुत अच्छा ™ के रूप में देखा जाता है, क्योंकि आप आंशिक रूप से कार्यों का विशेषज्ञ नहीं हो सकते हैं। अधिक जानकारी के लिए [मेरा यह जवाब] देखें (http://stackoverflow.com/questions/6380862/how-to-provide-a-swap-function-for-my-class/6380882#6380882)। – Xeo

+0

क्या आपको नेमस्पेस std में कुछ जोड़ने की अनुमति है? –

+2

@MichaWiedenmann, आपको std फ़ंक्शंस टेम्पलेट विशेषज्ञता (जैसे ऊपर दिए गए उदाहरण में) जोड़ने की अनुमति है – utnapistim

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