2012-12-05 15 views
6

पर टेम्पलेट, एक्सओआर और पॉइंटर्स का उपयोग करके बहुत क्रूर स्वैप स्वैप के ऐसे कार्यान्वयन का उपयोग करने के सबसे खतरे क्या हैं? थ्रेड सुरक्षा और खराब अनुकूलन के अलावा। यह कब विफल रहता है (counterexample)?मेमोरी

template<typename T> 
void swapViaMemory(T& left, T& right) { 
    if(&left == &right) { return ; } 

    unsigned int tSize = sizeof(T); 
    unsigned char* lPtr = reinterpret_cast<unsigned char*>(&left); 
    unsigned char* rPtr = reinterpret_cast<unsigned char*>(&right); 

    for(unsigned int i = 0; i < tSize; ++i) { 
     *(lPtr + i) ^= *(rPtr + i); 
     *(rPtr + i) ^= *(lPtr + i); 
     *(lPtr + i) ^= *(rPtr + i); 
    } 
} 

व्याकरण की गलतियों के लिए क्षमा करें, और वर्तनी (=

उत्तर

4

तो T एक सदस्य जो एक सूचक या उसके सदस्यों का एक और इस असफल हो जायेगी के संदर्भ में होता है (आशय यह सोचते हैं सूचक/संदर्भ सदस्य को हमेशा बिंदु/का उल्लेख के लिए है उस उदाहरण से संबंधित डेटा सदस्य)।

struct foo 
{ 
    foo() : i(), ref_i(i), ptr_i(&i) {} 
    int i; 
    int& ref_i; 
    int *ptr_i; 
}; 

तो दो foo वस्तुओं, कहते हैं कि f1 & f2swapViaMemory का उपयोग कर लगा दिया जाता था गमागमन, f1.ref_i और f1.ptr_if2.i और इसके विपरीत का उल्लेख/बिंदु के बाद,। इसके अलावा, संदर्भ सदस्य के मामले में, यह अनिर्धारित व्यवहार का आह्वान करता है क्योंकि संदर्भ को फिर से सीट करना अवैध है।

+0

पॉइंटर सदस्यों के लिए यह सच नहीं है जब तक कि आप 'यह असफल हो' का अर्थ नहीं उठाते हैं। –

+0

@LucDanton उत्तर में – Praetorian

+0

@Praetorian ओह, मुझे यह पसंद है। पॉइंटर्स स्वैप किए गए ऑब्जेक्ट्स के सदस्यों के बीच क्रॉस-पॉइंट होंगे। – shycha

4

यह आशय का सन्देश देने में विफल रहता है।

कौन सा कोड का प्राथमिक उद्देश्य है।

template<typename T> 
    typename std::enable_if<std::is_pod<T>, void>::type 
    swapViaMemory(T& left, T& right) 
{ 
    using std::swap; 

    swap(left, right); 
} 
+3

दाएं, जब तक आपका "इरादा" अभ्यास में कुत्ते के रूप में धीमा न हो जाए, तब तक आपके ग्राहक आपके "इरादे" के बारे में दो हूट नहीं देते हैं। यह नहीं कह रहा कि यह मामला यहां है, लेकिन सामान्य रूप से, कोड का प्राथमिक उद्देश्य मशीन भाषा को संकलित करना है ताकि हम * समस्याओं को हल कर सकें *। स्पष्टता हमेशा के लिए प्रयास की जानी चाहिए, लेकिन नौकरी को अच्छी तरह से और जल्दी से करने के लिए इसे हमेशा पिछली सीट लेनी चाहिए। –

+3

@ एडीएस। यह पूरी तरह से मामला नहीं है। वैल्यूटाइप पीओडी है, यहां तक ​​कि 'std :: copy' सीधे एसएसई-सक्षम 'memcpy' /' memmov' में अनुकूलित करेगा। आपको प्रोफाइल होना चाहिए। और फिर सवाल यह हो जाता है: "क्या मैं इस हैक *** का उपयोग *** *** कर सकता हूं", "मैं इस *** का उपयोग क्यों नहीं कर सकता *** ***" – sehe

+0

सहमत है, इसलिए मैंने अपनी टिप्पणी योग्यता प्राप्त की। मैं इस बयान से चिंतित था कि * "[इरादा] कोड का प्राथमिक उद्देश्य है।" *, जिसे मैं दृढ़ता से असहमत हूं। मैं ऊपर "कुत्ते के रूप में धीमा * धीमा * टाइप करने के लिए भी टाइप करना चाहता था। –

0

बुरी होने के अलावा obfuscated यह विफल रहता है अगर बाएं और दाएं बिंदु एक ही पते पर इंगित करता है।

a^a = 0 के बाद से (जो आप इस 'चाल' के लिए करते हैं)

तो left == right (और मान लेते हैं कि यह एक 1 बाइट युक्त 'a' तो फिर तुम क्या करोगे इकाई है देता है:

a^a = 0 
0^a = a 
a^a = 0 
+6

कैसे? - ध्यान दें कि यह समानता के लिए कुछ भी नहीं करता है। –

5

यह अपरिभाषित व्यवहार करता है, तो आह्वान टी एक मामूली प्रतिलिपि प्रकार नहीं है।

1

कहो के लिए:

struct B{ 
    virtual ~B() {} 
}; 
struct X : B 
{ 
    int x; 
    ~X() { std::cout << x; } 
}; 
struct Y : B 
{ 

}; 

//... 
X x = X(); 
Y y; 
swapViaMemory<B>(x,y);