2013-03-13 9 views
9

इस तरह का कोड अक्सर आर-मूल्य के संदर्भ में लेख में देखा जाता है:क्या कंपाइलर स्वचालित रूप से अंतराल के अंतिम उपयोग के लिए std :: move उत्पन्न कर सकता है?

Dave Abrams: Move It With Rvalue References

void g(X); 

void f() 
{ 
    X b; 
    g(b);    // still need the value of b 
    … 
    g(std::move(b)); // all done with b now; grant permission to move 
} 

एक संकलक इस अनुकूलन स्वचालित रूप से, यानी उत्पन्न कर सकता है एक एल-मूल्य वैसे भी विलुप्त होने जा रही है पता लगाने के लिए और से स्थानांतरित किया जा सकता है, या यह मानक का उल्लंघन होगा, एक सामान्य मामला मानते हुए संकलक को एक्स क्लास के लिए लागू, प्रतिलिपि या विनाश के बारे में कुछ भी नहीं पता है?

यदि ऐसी अनुकूलन की अनुमति है, तो क्या यह अभ्यास में कुछ कंपाइलर द्वारा किया जाता है?

+3

हां। किसी तरह की संभावना नहीं। एक कंपाइलर तब तक ऐसा कर सकता है जब तक कि यह मानक (तथाकथित "जैसा-अगर नियम") का उल्लंघन न हो। –

+1

रोबोट ने क्या कहा, हालांकि उत्तर आम तौर पर "नहीं" होगा। यदि आप स्थानीय चर लौटाते हैं तो स्वचालित चाल प्राप्त करने की गारंटी है, हालांकि (कुछ स्थितियों को मॉड्यूल करें, जैसे रिटर्न प्रकार स्थानीय चर के समान प्रकार है)। – Xeo

+0

@ आर। मार्टिन्हो फर्नांडीस खैर, सवाल * विशेष रूप से * पूछता है कि क्या यह मानक का उल्लंघन करेगा, इसलिए मुझे पूरा यकीन नहीं है कि आपकी टिप्पणी इसमें क्या शामिल है। (जब तक कि आपने टिप्पणी के बाद इसे संपादित नहीं किया था?) – us2012

उत्तर

7

संख्या पर विचार करें:

using X = std::shared_ptr<int>; 
void g(X); 
void f() { 
    X b = std::make_shared<int>(); 
    int &i = *b; 
    g(b);    // last use of 'b' 
    i = 5; 
} 

सामान्य में, संकलक कल्पना नहीं कर सकते कि प्रतियां, चाल के शब्दों और X का विनाशकर्ता फेरबदल सभी के उपयोग के आसपास के कोड पर विश्लेषण के प्रदर्शन के बिना एक वैध बदलाव किया जाएगा b (यानी, पूरे f, g, और उसमें उपयोग किए जाने वाले सभी प्रकार)।

दरअसल, कुछ मामलों में पूरे कार्यक्रम विश्लेषण आवश्यक हो सकता है:

using X = std::shared_ptr<std::lock_guard<std::mutex>>; 
std::mutex i_mutex; 
int i; 
void g(X); 
void f() { 
    X b = std::make_shared<std::lock_guard<std::mutex>>(i_mutex); 
    g(b);    // last use of 'b' 
    i = 5; 
} 

तो b ले जाया जाता है, यह अन्य धागे कि i के लिए उपयोग सिंक्रनाइज़ i_mutex उपयोग करने के खिलाफ एक डेटा दौड़ परिचय देता है।

+0

अच्छा काउंटररेक्स नमूना, जो दिखाता है कि संकलक के लिए एल-वैल्यू के कुछ विशेष उपयोग को साबित करना मुश्किल है, वास्तव में इसके विनाश से पहले आखिरी आखिरी है, क्योंकि अभी भी एक पॉइंटर या इसके आसपास लटकने का संदर्भ हो सकता है। – Suma

+0

@ सुमा यह केवल lvalues ​​तक पहुंच नहीं है; 'बी' एक म्यूटेक्स लॉक गार्ड हो सकता है। ऊपर मेरा नया उदाहरण देखें। – ecatmur

+0

मुझे लगता है कि बचने का विश्लेषण जीसी रनटाइम्स में इस्तेमाल किया गया है, यह साबित करने के लिए कि स्मृति को आवंटित किया जा सकता है यह साबित करने के लिए नियोजित किया जा सकता है कि 'बी' मेमोरी के लिए कोई भी वैध संदर्भ 'जी' के बाद पहुंच योग्य नहीं है। कस्टम कन्स्ट्रक्टर के साथ ऑब्जेक्ट और स्वचालित रूप से इनकार कर दिया जा सकता है, लेकिन सरल चीजों के लिए 'स्ट्रक्चर {int x, int y, int z}' escale विश्लेषण विश्वसनीय हो सकता है ... मुझे लगता है। –

4

(...) एक सामान्य मामला मानते हुए संकलक को एक्स क्लास के लिए लागू, प्रतिलिपि या विनाश के बारे में कुछ नहीं पता है?

नहीं, कंप्यूटर्स को विश्वास के आधार पर अनुकूलन करने की अनुमति नहीं है।

स्पष्टता के लिए, यह प्रश्न elision की प्रतिलिपि बनाने के लिए असंबंधित है: कंपेलरों को प्रतिलिपि बनाने की अनुमति दी जा सकती है, लेकिन वे प्रतियां बढ़ने के लिए प्रतियां नहीं बदल सकते हैं।

+0

अच्छा, कभी-कभी वे होते हैं, उदा। कॉपी-एलीशन (उदाहरण के लिए रिटर्न वैल्यू ऑप्टिमाइज़ेशन) के मामले में - उस मामले में विश्वास करने की अनुमति है कि एक प्रोग्रामर ने कॉपी कन्स्ट्रक्टर को उचित तरीके से कार्यान्वित किया है। मुझे लगता है कि इस विशेष मामले में कंपाइलर को यह "विश्वास" रखने की अनुमति देने के लिए मानक में कुछ भी नहीं है, जो अनुकूलन को असंभव बनाता है। – Suma

+3

वह अनुकूलन विश्वास पर आधारित नहीं है। यह इस तथ्य पर आधारित है कि मानक स्पष्ट रूप से परिणामों को अनदेखा करने की अनुमति देता है। – Puppy

4

एक संकलक यह कर सकता है? केवल एक स्पष्ट भाषा विस्तार के रूप में, क्योंकि मानक उन्हें इसके बिना अनुकूलन करने की अनुमति नहीं देता है।

क्या वे इसे करते हैं? नहीं। g(b) का अर्थ g और b की परिभाषा पर आधारित होना चाहिए। g कुछ कॉल करने योग्य प्रकार होना चाहिए, जिसमें एक अधिभार है जो b को कुछ रूपांतरित कर सकता है। सभी उपलब्ध g एस की परिभाषा तक पहुंच और b की परिभाषा को देखते हुए, आपको बिल्कुल निर्धारित करने में सक्षम होना चाहिए कि कौन सा फ़ंक्शन कॉल किया जाएगा।

इस "अनुकूलन" को अनुमति देने के लिए अब यह असंभव है। g(b) एक चाल प्रदर्शन कर सकता है, और हो सकता है कि यह वास्तव में g(b) फ़ंक्शन में होने पर निर्भर करता है। यह एक अच्छी बात नहीं है।

return को इससे दूर जाने की अनुमति है, लेकिन केवल इसलिए कि इसका अभी भी वही अर्थ है। return bb से b से आगे बढ़ने का प्रयास करेगा यदि b एक मूल्य-प्रकार है जो जीवनकाल फ़ंक्शन के दायरे तक सीमित है।

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