2011-05-27 5 views
5

मैं (प्रशिक्षण के उद्देश्य के लिए) एक बुलबुला क्रमबद्ध टेम्पलेट समारोह को लागू किया गया था:कोई असाइनमेंट स्वैप का उपयोग करने के लिए कोई स्पष्ट कमी है?

template<typename iterInput, 
     typename predicate> 
void BubbleSort(iterInput first1,iterInput last1,predicate func) 
{ 
    bool swapped(false); 
    do 
    { 
     swapped = false; 
     iterInput begin = first1; 
     iterInput beginMinus = first1; 
     ++begin; 
     for (;begin != last1; begin++,beginMinus++) 
     { 
      if (func(*beginMinus,*begin)) 
      { 
       std::swap(*beginMinus,*begin); 
       swapped = true; 
      } 
     } 
    } 
    while(swapped); 
} 

जब मुझे एहसास हुआ है कि यह समारोह इस तरह कोई असाइनमेंट ऑपरेटर के साथ वर्ग के लिए काम नहीं करेगा, (मुझे बुरा नाम के लिए माफ कर दो): '= NoCopyable :: ऑपरेटर':

class NoCopyable 
{ 
public: 
    explicit NoCopyable(int value) : value_(value) {} 
    NoCopyable(const NoCopyable& other) : value_(other.value_) {} 
    ~NoCopyable() {} 
    bool operator<(const NoCopyable& other) { return value_ < other.value_; } 
    void setValue(int value) { value_ = value; } 
    std::ostream& print(std::ostream& os) const { return os << value_; } 
private: 
    NoCopyable& operator=(const NoCopyable& other); 
    int value_; 
}; 

std::ostream& operator<<(std::ostream& os, const NoCopyable& obj) 
{ 
    return obj.print(os); 
} 

struct PrintNoCopyable 
{ 
    void operator()(const NoCopyable& noCopyable) { std::cout << noCopyable << '\n'; } 
}; 

संकलक इस त्रुटि त्रुटि 1 त्रुटि C2248 को जन्म देती है निजी सदस्य कक्षा में घोषित नहीं पहुँच सकता 'NoCopyable'

तो, मैं थोड़ा कोड को संशोधित किया है एसटीडी के बजाय का उपयोग कर :: स्वैप स्वैप समारोह के अपने संस्करण कार्य करते है, यहाँ कोड है:

template<typename T1, 
     typename T2> 
void noAssignmentSwap(T1& t1,T2& t2) 
{ 
    T1 temp(t1); 
    t1.~T1(); 
    new (&t1) T1(t2); 
    t2.~T2(); 
    new (&t2) T2(temp); 
} 

कोड को संकलित करता है और सही परिणाम देता है। हालांकि मुझे पूरी तरह से यकीन नहीं है, मुझे एक सटर के लेख को याद है जो आपको जीवन के समय वस्तुओं के साथ खेलने से बचने का सुझाव देता है। लेख आपको वास्तव में बिना किसी वास्तविक कारण के आग से खेलकर आपको चेतावनी देता है। यदि टी 1 या टी 2 की कॉपी कन्स्ट्रक्टर फेंक सकता है तो मैं अपवाद सुरक्षा में समस्या देख सकता हूं। हालांकि असाइनमेंट ऑपरेटर को फेंकने की अनुमति देने पर मानक संस्करण में एक ही समस्या है।

यहां प्रश्न, क्या आप स्वैप के इस संस्करण में कोई संभावित कमी देख सकते हैं?

चीयर्स

+0

स्पष्ट विनाशक कॉल शायद ही कभी आवश्यक हैं ... iffy imho –

+1

दिखता है क्यों आप स्वैप में दो अलग-अलग प्रकार का उपयोग कर रहे हैं? यदि वे एक ऑब्जेक्ट के लिए प्लेसमेंट कन्स्ट्रक्टर का उपयोग कर अलग हैं तो दूसरे के पते के साथ बहुत बुरा होगा ... – 6502

+0

@ गुड पॉइंट, यह सिर्फ एक टेम्पलेट पैरामीटर –

उत्तर

6

अंतर यह है कि जब असाइनमेंट ऑपरेटर विफल रहता है, तो आपके पास अभी भी वही संख्याएं होती हैं।

यदि आप एक वस्तु को नष्ट करते हैं और एक नया निर्माण करने में विफल रहते हैं, तो एक वस्तु खो जाती है! यदि यह एक कंटेनर का हिस्सा था, तो कंटेनर का राज्य शायद अमान्य भी है।

3

यह कोड के भविष्य के मेंटेनर को भ्रमित हो सकता है।

8

किसी और चीज के अलावा, यदि किसी वर्ग के पास असाइनमेंट ऑपरेटर नहीं है, तो इसके डिजाइनर शायद इसे स्वैप करने का इरादा नहीं रखते थे। अगर उन्होंने ऐसा किया, तो संभवतः उन्होंने कॉपी निर्माण को भी अक्षम कर दिया, इसलिए आपका नया स्वैप फ़ंक्शन अभी भी काम नहीं करेगा।

आपके दावे के लिए कि मानक लाइब्रेरी कंटेनरों को असाइनमेंट की आवश्यकता नहीं है - यह तब तक सच है जब आप वास्तव में उनके साथ कुछ भी उपयोगी नहीं करना चाहते हैं। क्या यह कोड आपके लिए संकलित करता है?

#include <vector> 
using namespace std; 

struct A { 
    private: 
     void operator=(const A &); 
}; 

int main() { 
    vector <A> v; 
    v.push_back(A()); 
    v[0] = A();  // assignment needed here 
} 

मुझे लगता है कि यह नहीं होगा।

+0

+1 होना चाहिए। अच्छा उत्तर। बहुत सटीक कहा! – Nawaz

+0

@ नील बटरवर्थ अगर ऑब्जेक्ट की कॉपी कन्स्ट्रक्टर अक्षम है तो वस्तु को एसटीएल कंटेनर के साथ उपयोग नहीं किया जा सकता है, इसलिए सॉर्ट करने के लिए बहुत कुछ नहीं है। –

+0

@Alessandro तो आप उन वस्तुओं से निपट रहे हैं जिन्हें असाइन नहीं किया जा सकता है, लेकिन कॉपी किया जा सकता है? मेरे अनुभव में बहुत दुर्लभ हैं। और आपका प्रश्न स्पष्ट रूप से स्वैप() के बारे में है। –

4

आपको असाइनमेंट ऑपरेटर की बजाय एक प्रतिलिपि ctor की आवश्यकता है, लेकिन दोनों पर्याप्त रूप से समान हैं कि कम से कम एक सामान्य मामले में, आपके पास दोनों होंगे या आपके पास नहीं होगा। IOW, मुझे नहीं लगता कि यह आम तौर पर बहुत कुछ पूरा करता है।

मैं इसे xor-swap चाल के साथ सही श्रेणी में रखूंगा: दिलचस्प, लेकिन आम तौर पर बेकार।

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

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