2012-01-13 15 views
6

में भ्रम बाध्यकारी मैं तीन फ़ंक्शन को कॉल मुझे लगता है कि इलाज किया जाना चाहिए (के बारे में) एक ही है, लेकिन स्पष्ट रूप से वे नहीं हैं। मैं समझने की कोशिश कर रहा हूं कि क्यों तीनों में से एक संकलित नहीं करता है (g ++ -std = C++ 0x)।rvalue सी ++

// Minimal example to reproduce a compile bug I want to understand. 

#include <iostream> 
#include <string> 

using namespace std; 


void bar(const string &&x) { cout << "bar: " << x << endl; } 

string returns_a_string() { return string("cow"); } 

int main(int argc, char *argv[]) 
{ 
    bar(string("horse"));  // ok 
    bar(returns_a_string()); // ok 
    string aardvark = "aardvark"; 
    bar(aardvark);   // not ok, fails to compile, error in next comment 
    /* 
     rvalue-min.cpp:29:22: error: cannot bind ‘std::string {aka std::basic_string<char>}’ lvalue to ‘const string&& {aka const std::basic_string<char>&&}’ 
     rvalue-min.cpp:10:6: error: initializing argument 1 of ‘void barR(const string&&)’ 
    */ 
} 

यह सवाल C++0x rvalue references - lvalues-rvalue binding, की तर्ज पर एक सा है, तो यह वहाँ जवाब है लेकिन, मेरी क्षमा याचना, मैं नहीं यह पता चुलाना में सक्षम था।

मैं क्या चाहते हैं स्ट्रिंग किसी भी प्रकार के साथ अपने समारोह बार() कहते हैं और यह सिर्फ काम करने के लिए सक्षम होने के लिए है। void barR(const string &x) को परिभाषित करने के लिए पर्याप्त है, लेकिन मैं वास्तव में समझना चाहता हूं क्यों।

समझने क्यों तीसरी कॉल अलग है में किसी भी मदद के लिए बहुत धन्यवाद।

+3

ध्यान दें कि यदि आप वास्तव में कुछ भी एक * लगातार * rvalue संदर्भ में उपयोगी नहीं कर सकते। आम तौर पर आप 'बार (std :: string &&)' घोषित करना चाहते हैं। –

+0

@KerrekSB - अच्छा बिंदु – jma

उत्तर

14

आर-मूल्य संदर्भ मानकों के उद्देश्य पता लगाने के लिए एक वस्तु एक r-मूल्य है विशेष रूप से है। क्योंकि यदि कोई ऑब्जेक्ट एक आर-वैल्यू है, तो फ़ंक्शन जानता है कि इसका फिर से उपयोग नहीं किया जाएगा, इसलिए यह जो कुछ भी चाहता है वह कर सकता है। यदि कोई एल-वैल्यू आर-वैल्यू संदर्भ से जुड़ा हो सकता है, तो इसका मतलब यह होगा कि जिस पहचान का मैं बात कर रहा था वह वास्तव में नहीं हो रहा था।

आप इन कार्यों में से एक के लिए एक एल-मूल्य पास करना चाहते हैं, तो आप std::move उपयोग करने के लिए की जरूरत है। आर-वैल्यू संदर्भ लेने वाले फ़ंक्शन में std::move के माध्यम से ऑब्जेक्ट पास करना यह कहने जैसा है, "यहां, इस ऑब्जेक्ट को लें, इसे दबाएं, मुझे कोई परवाह नहीं है कि इसके साथ क्या होता है"।

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

+0

इस उत्तर इस लेख में एक उदाहरण से असहमत नहीं है (विशेष रूप से देखने के लिए: Ctrl + F "// रेखा 31"): http://blogs.msdn.com/b/vcblog/archive/2009/02/03 /rvalue-references-c-0x-features-in-vc10-part-2.aspx –

+0

@sftrabbit: हाँ यह करता है, लेकिन यह भाषा मानक के साथ सहमत हैं (और यह भी जीसीसी, जो कि लेख में कोड को खारिज कर दिया के साथ)। –

+0

धन्यवाद। मैंने इस आलेख को पहले लेख में देखा होगा लेकिन इसे जांचने के लिए कभी भी गोल नहीं हुआ। –

4

आप std::move उपयोग करने के लिए की जरूरत है। यह ठीक काम करता है:

bar(std::move(aardvark)); 
+0

पर्याप्त मेला, हालांकि यह ग्राहक पर काम लगाता है। जानना अच्छा है, धन्यवाद, धन्यवाद। – jma

+1

@jma: क्लाइंट को ऐसा करना है क्योंकि क्लाइंट ऑब्जेक्ट से बाहर निकलने के लिए फ़ंक्शन के लिए स्पष्ट अनुमति दे रहा है। (यही कारण है कि कॉन्स अजीब है।) आपको केवल सब कुछ लेने के लिए (const std :: string और rhs) कोड होना चाहिए। –

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