2015-12-11 3 views
5
template <typename T> 
void myswap(T a,T b) 
{ 
    T temp = a; 
    a = b; 
    b = temp; 
} 
int main() 
{ 
    int m(20),n(30); 
    myswap(ref(m),ref(n)); 
    //m is still 20 and n is still 30 
} 

एम और एन के मूल्यों का अंतर क्यों नहीं है? std::ref में एक इंक्रेमेंट फ़ंक्शन में लिपटे मान को मूल चर में मूल्य परिवर्तन (स्टैक फ्रेम में परिवर्तनीय जो कॉल फ़ंक्शन कहते हैं) में परिणाम बदलता है। या, std::ref उपयोग प्रतिबंधित/सीमित है?std :: ref और swap function अच्छी तरह से काम नहीं कर रहा है

उत्तर

8

std::ref (और इसके संबंधित std::reference_wrapper) मानक पुस्तकालय में बहुत विशिष्ट उपयोग मामलों के लिए डिज़ाइन किया गया एक उपकरण है और केवल उन लोगों के लिए उपयोग किया जाना चाहिए; यदि आप इसे अपने स्थानों पर उपयोग करना चाहते हैं, तो आपको इसे विस्तार से समझना होगा और यह सम्मान करना होगा कि यह क्या करता है।

मूल रूप से, reference_wrapper संदर्भ के मुकाबले एक सूचक के करीब है। तो अपने स्वैप समारोह में एक सूचक स्थानापन्न और आप देखेंगे वहाँ कोई कारण नहीं है कि ग्रहण करने के लिए कि यह वास्तव में स्वैप जाएगा:

void myswap(int* a, int* b) 
{ 
    int* temp = a; 
    a = b; 
    b = temp; 
} 
+0

या 'std :: swap' – 101010

+0

का उपयोग करें पहला वाक्य थोड़ा भ्रामक है।बेशक 'std :: ref' मानक लाइब्रेरी तक सीमित नहीं है (जैसा कि आप इसे इसके बाद भी नोट करते हैं) –

1

आपका myswapमूल्य द्वारा तत्वों लेता है।

अनिवार्य रूप से आप फ़ंक्शन के स्थानीय दायरे पर दो संदर्भ (std::reference_wrapper एस) को स्वैप करते हैं।

वे जो मान इंगित करते हैं वे नहीं बदलेंगे।


template <typename T> void incrementer(T a) { ++a; } int a = 20; 

इस मामले में int&with में रूपांतरण नहीं है:

operator T&() const noexcept { return *_ptr; } 

अपने कोड में, दूसरे हाथ पर:

T temp = a; 

बस प्रतिलिपि निर्माता कॉल करेंगे, जो अंतर्निहित सूचक की प्रतिलिपि बनाता है:

reference_wrapper(const reference_wrapper&) noexcept = default; 

तो, अगले तर्ज पर आप फिर से सूचक कॉपी:

reference_wrapper& operator=(const reference_wrapper& x) noexcept = default; 
+0

@ करोलि: मैं फ़ंक्शन में संदर्भ_वापर पास कर रहा हूं। सादा पूर्णांक नहीं। http://stackoverflow.com/questions/26766939/difference-between-stdreference-wrapper-and-simple-pointer?lq=1 (संदर्भ_वापर और उसके लाभ के बारे में)। –

+0

@ 101010: क्या मैं यह नहीं कह रहा था? इसे स्पष्ट करने के लिए मुझे संपादित करने दें। –

+0

हां, वे मूल्य से तत्व (प्रकार std :: ref) लेते हैं। लेकिन ms n के लिए एक प्रति myswap फ़ंक्शन में नहीं बनाई गई है। दो नए संदर्भ अभी भी अंतिम स्टैक फ्रेम में बनाए गए एम एंड एन को इंगित कर रहे हैं। –

4

आपका कोड दो अस्थायी std::reference_wrapper वस्तुओं बनाता है और उन्हें अदला-बदली, ताकि वे विभिन्न वस्तुओं को देखें। ऐसा होता है कि आप दो reference_wrapper ऑब्जेक्ट्स को स्वैप करते हैं, न कि उनके लक्ष्य।

आप मैन्युअल रूप से लिखना क्या समारोह टेम्पलेट कारण उत्पन्न होगा व्यवहार के लिए स्पष्ट किया जाना चाहिए:

void myswap(std::reference_wrapper<int> a, std::reference_wrapper<int> b) 
{ 
    std::reference_wrapper<int> temp = a; 
    a = b; 
    b = a; 
} 

जाहिर है इस int वस्तुओं, केवल reference_wrapper वस्तुओं नहीं बदलता है।

यदि आप myswap<int&>(m, n) पर कॉल करने के लिए संदर्भ देने के लिए myswap पर बल देने के लिए मजबूर कर रहे हैं, तो आप reference_wrapper का उपयोग कर अनुकरण नहीं कर सकते हैं। लेकिन आपको वास्तव में myswap को ठीक करना चाहिए, क्योंकि यह अब जिस तरह से लिखा गया है, वह बेकार है।

+0

दरअसल, लेकिन अस्थायी स्टैक फ्रेम में अस्थायी रूप से एम और एन को इंगित नहीं करना चाहिए? एक वृद्धि कार्य में std :: ref में एक चर को पास करें और आप देखेंगे कि वैल्यू विड अपडेट हो गया है। वृद्धि कार्य में एक अस्थायी बनाया नहीं है? फिर, मूल चर में परिवर्तन कैसे दिखाई देता है। –

+0

@ जोन: हाँ, यह 'मूल्य से' लेता है। टेम्पलेट शून्य वृद्धिकर्ता (टी ए) { ++ ए; } int a = 20; वृद्धिकर्ता (रेफरी (ए)); // ए 21 है –

+0

'context_wrapper' एक वृद्धि ऑपरेटर का समर्थन नहीं करता है, इसलिए वृद्धि कार्य एक रूपांतरण को 'int'' का कारण बनता है और लक्ष्य को बढ़ाता है। स्वैप फ़ंक्शन केवल कॉपी कन्स्ट्रक्टर और कॉपी असाइनमेंट का उपयोग करता है, जो 'context_wrapper' _does_ समर्थन' है, इसलिए वे ऑपरेशन सीधे 'संदर्भ_वापर' पर काम करते हैं, लक्ष्य पर नहीं। –

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