2013-08-09 8 views
8

लौट रहा है एक समारोह जो एक वेक्टर या सेट रिटर्न:नकल से बचने के लिए कैसे करने के लिए जब मैं

set<int> foo() { 
    set<int> bar; 
    // create and massage bar 
    return bar; 
} 

set<int> afoo = foo(); 

इस मामले में, मैं समारोह foo() में एक अस्थायी मेमोरी की जगह बनाने, और फिर असाइन करें प्रतिलिपि करके afoo पर। मैं वास्तव में इस प्रति से बचना चाहता हूं, किसी भी आसान तरीके से मैं इसे C++ 11 में कर सकता हूं? मुझे लगता है कि इसे रैवल्यू चीज के साथ करना है।

ठीक है, प्रश्न के लिए अद्यतन करें: यदि मैं स्वयं द्वारा परिभाषित एक वस्तु वापस करने जा रहा हूं, वेक्टर या सेट चीज़ नहीं, तो क्या इसका मतलब है कि मुझे एक चालक कन्स्ट्रक्टर को परिभाषित करना चाहिए? इस तरह:

class value_to_return { 
    value_to_return (value_to_return && other) { 
    // how to write it here? I think std::move is supposed to be used? 
    } 
} 

धन्यवाद !!!

+4

अब जो मिला है वह सी ++ 11 में कोई प्रतिलिपि नहीं बनाएगा। यह चाल कर सकता है, लेकिन यहां तक ​​कि उनको लगभग निश्चित रूप से [एन/आरवीओ] (http://en.wikipedia.org/wiki/Return_value_optimization) द्वारा अनुकूलित किया जाएगा। –

+11

"जब मैं वापस आती हूं तो प्रतिलिपि से कैसे बचें" - 10 साल से अधिक समय तक रिलीज़ किए गए कंपाइलर के साथ संकलित करें। –

+0

मैं उन सभी उत्तरों को कम करने के लिए बहुत मोहक हूं जो चाल/रावल का उल्लेख नहीं करते हैं। –

उत्तर

5

return value optimization देखें। एक आधुनिक कंपाइलर इस स्थिति को अनुकूलित करेगा, और इन तरह की सीधी स्थितियों में, किसी भी प्रमुख कंपेलरों पर कोई प्रतिलिपि नहीं बनाई जाएगी।

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

-3

मैं आमतौर पर

void foo(set<int> *x) 

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

संपादित करें: मैंने यह तर्क देने के लिए तर्क प्रकार बदल दिया है कि x बदला जा सकता है।

 set<int> s; 
     foo(&s); 

यह केवल तभी पसंद किया जाता है जब आपके पास पुराना कंपाइलर हो। मुझे लगता है कि कुछ परियोजनाओं के साथ मामला हो सकता है।

और, बेहतर काम करने के लिए या तो सी ++ 11 के साथ चाल semantics का उपयोग करने के लिए होगा। या कंटेनर लौटने और आधुनिक कंपाइलरों में आरवीओ में देखने के लिए आगे बढ़ें।

+0

मैं इसे वोट दे रहा हूं क्योंकि यह केवल * उत्तर है जो आउटपुट पैरामीटर में गुजरने का प्रस्ताव करता है। एक सही उत्तर में आरवीओ शामिल होगा और साथ ही रचनाकारों को भी स्थानांतरित किया जाएगा। –

+8

लगभग आउटपुट पैरामीटर का प्रस्ताव देने के लिए इसे _down_ वोट करने का लुत्फ उठाया। –

+0

@EdS .: आउटपुट पैरामीटर भयानक हैं। – Puppy

18

मोडेम C++ कम्पाइलर को लागू करेगा:

  • टी एक सुलभ प्रतिलिपि है या निर्माता ले जाते हैं, संकलक प्रतिलिपि छिपाना चुन सकते हैं: एक प्रकार T दिया। यह तथाकथित (नामित) return value optimization (RVO) है, जिसे सी ++ 11 से पहले भी निर्दिष्ट किया गया था और अधिकांश कंपेलरों द्वारा समर्थित है।
  • अन्यथा, यदि टी move constructor है, तो टी को स्थानांतरित किया गया है (सी ++ 11)।
  • अन्यथा, यदि टी की प्रतिलिपि बनाने वाला है, टी की प्रतिलिपि बनाई गई है।
  • अन्यथा, एक संकलन-समय त्रुटि उत्सर्जित होती है।
+0

अगर मैं गलत हूं, तो कृपया मुझे सही करें, लेकिन AFAIK रिटर्न वैल्यू ऑप्टिमाइज़ेशन केवल तभी काम करता है जब आप सीधे इस तरह के रिटर्न स्टेटमेंट में ऑब्जेक्ट का निर्माण करते हैं: 'वापसी (सेट ) (...); 'एक बुद्धिमान कंपाइलर कोड को बदल सकता है इस रूप में सवाल में, लेकिन अधिक जटिल कार्यों के लिए मैं कल्पना करता हूं कि यह काम नहीं करेगा। ओपी के मामले में – cmaster

+0

@cmaster, आरवीओ भी लागू होगा। आरवीओ के संबंध में मेरे उत्तर में विकी लिंक पढ़ें। :) – billz

+0

@cmaster: किसी नामित चर को वापस करने के मामले में एक प्रति को अनुकूलित करना आमतौर पर एनआरवीओ कहा जाता है, जिसे रिटर्न वैल्यू ऑप्टिमाइज़ेशन नाम दिया जाता है, और इसे कई वर्षों पहले लागू किया गया है। – JohannesD

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