2016-03-04 12 views
6

से डेटा को स्थानांतरित करने की अनुमति देने का सबसे अच्छा तरीका क्या है कल्पना कीजिए कि मेरे पास एक वर्ग है जिसका मुख्य उत्तरदायित्व डेटा कंटेनर को पॉप्युलेट करना है। मैं इस वर्ग से डेटा को स्थानांतरित करना चाहता हूं। तो मेरे पास है:सी ++ कक्षा सदस्य (std :: move वाक्यविन्यास)

class cCreator 
{ 
public: 
    void generate() 
    { 
     ///generate the content of data_ and populate it 
     .... 
     .... 
    } 

    //variation 1 
    std::vector<int>&& getData1() 
    { 
     return std::move(data_); 
    } 

    //variation 2 
    std::vector<int> getData2() 
    { 
     return std::move(data_);  
    } 
private: 
     std::vector<int> data_ 
}; 

एस getData() के विविधता 1 और विविधता 2 के बीच क्या अंतर है। फ़ंक्शन परिभाषा से & & को छोड़ने पर क्या परिवर्तन होता है ??

+1

पक्ष पर एक छोटी सी टिप्पणी: ध्यान दें कि 'getData()' के कॉल को सदस्य को नष्ट कर दिया गया है, इसलिए आप फ़ंक्शन में रावल्यू रेफ-क्वालीफायर जोड़ना चाहेंगे: 'std :: vector cCreator :: extractData() && '। इस तरह, आप कॉलर को डेटा निकालने के लिए एक रावल्यू संदर्भ प्रदान करने के लिए मजबूर करते हैं, जिससे यह स्पष्ट हो जाता है कि सदस्य को ऑब्जेक्ट से हटाया जा रहा है। यही है, 'obj.extractData() 'अब संकलित नहीं होगा, लेकिन' std :: move (obj) .extractData() 'will। – ComicSansMS

उत्तर

3

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

cCreator c1, c2; 
c1.getData1(); // no move 
std::vector<int> v1 = c1.getData1(); // move directly from data_ 
            // into v1. 
c2.getData2(); // move to temporary, which isn't used. 
std::vector<int> v2 = c2.getData1(); // move from data_ to temporary, 
            // then move from temporary to v2. 
+0

आरवीओ पूरा होने पर अंतिम मामला जरूरी नहीं है, लेकिन व्यवहार होगा जो आपने GetData() नामकरण के विरुद्ध – galinette

1

संस्करण 1 शायद एक बुरा विचार है, f(x.getData()) तरह बातें या चल रहा हो सकता है नहीं f के हस्ताक्षर के आधार पर। सामान्य तौर पर हम किसी भी move कोड में स्पष्ट होना चाहता हूँ, तो आप कम से कम की तरह कुछ होना चाहिए:

std::vector<int>&& getData() && 
{ 
    return std::move(data_); 
} 

तो है कि अब इस कदम स्पष्ट हो गया है: f(std::move(x).getData()), और आप शायद एक अधिभार प्रदान करना चाहते हैं सिर्फ const & के लिए देखने के लिए।

संस्करण 2 ठीक होगा यदि उसके पास दूसरा नाम था। मेरे अनुभव में, 99% लोग getX को एक गैर-संशोधित संचालन के रूप में देखते हैं। बेहतर इसे releaseData पर कॉल करें, जो unique_ptr::release के नामकरण के अनुरूप है।

+0

+1 वर्णित किया है। अन्य नामकरण सुझाव: moveData, popData, peekData। मैं कभी भी "पाने" समारोह का उपयोग नहीं करता क्योंकि इरादा हमेशा अस्पष्ट है। एक कॉन्स एक्सेस के लिए सर्वश्रेष्ठ उपयोग डेटा(), और संचालन को संशोधित करने के लिए इन स्पष्ट कार्रवाई नामों में से एक। – galinette

+0

@galinette मुझे एक ही राय थी, फिर 'get (tuple)' हुआ और उसने 'getX' कार्यों के लिए बहुत सारे दरवाजे खोले। – sbabbi

1

मुझे लगता है कि इस विशिष्ट मामले में जहां कंटेनर निकाला गया है (स्थानांतरित) एक एसएलएल वेक्टर है, std :: स्वैप एक मान्य विकल्प होगा। तो बस की आपूर्ति:

const std::vector<int>& getData() const; 
std::vector<int>& getData(); 

सुरक्षित रूप से डेटा निकालने के अगर वह इतना चाहता है उपयोगकर्ता woudl सक्षम करें। यह केवल व्यवहार्य विकल्प हो सकता है यदि किसी कारण से सी ++ 11 उपलब्ध नहीं है।

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