2016-03-11 10 views
16

का रिटर्न वैल्यू ऑप्टिमाइज़ेशन मैं टुपल/संबंधों के मामले में रिटर्न वैल्यू ऑप्टिमाइज़ेशन में देख रहा हूं और जिस व्यवहार का मैं पालन करता हूं वह उतना ही नहीं है जितना मैं उम्मीद करता हूं। नीचे दिए गए उदाहरण में मैं उम्मीद करता हूं कि चलने वाले अर्थशास्त्र को लात मारने की उम्मीद है, जो यह करता है, लेकिन एक प्रतिलिपि है जो बनी हुई है। अनुकूलित में नीचे से उत्पादन होता है:टुपल/टाई

Test duo output, non_reference tuple 
Default constructor invoked 
Parameter constructor invoked 
Copy constructor invoked 
Move Assignment operator invoked 
100 

समारोह अंदर टपल बनाने में प्रति निर्माता के आह्वान के अनावश्यक लगता है। क्या इसे हटाने का कोई तरीका है? मैं एमएसवीसी 2012 कंपाइलर का उपयोग कर रहा हूँ।

#include <iostream> 
#include <tuple> 

class A 
{ 
public: 
    int value; 
    A() : value(-1) 
    { 
     std::cout << "Default constructor invoked" << std::endl; 
    } 

    explicit A(const int v) : value(v) 
    { 
     std::cout << "Parameter constructor invoked" << std::endl; 
    } 

    A(const A& rhs) 
    { 
     value = rhs.value; 
     std::cout << "Copy constructor invoked" << std::endl; 
    } 

    A(const A&& rhs) 
    { 
     value = rhs.value; 
     std::cout << "Move constructor invoked" << std::endl; 
    } 

    A& operator=(const A& rhs) 
    { 
     value = rhs.value; 
     std::cout << "Assignment operator invoked" << std::endl; 
     return *this; 
    } 

    A& operator=(const A&& rhs) 
    { 
     value = rhs.value; 
     std::cout << "Move Assignment operator invoked" << std::endl; 
     return *this; 
    } 
}; 

std::tuple<A, int> return_two_non_reference_tuple() 
{ 
    A tmp(100); 

    return std::make_tuple(tmp, 99); 
} 

int main(int argc, char* argv[]) 
{ 

     std::cout << "Test duo output, non_reference tuple" << std::endl;  
     A t3; 
     int v1; 
     std::tie(t3, v1) = return_two_non_reference_tuple(); 
     std::cout << t3.value << std::endl << std::endl; 

     system("pause"); 
     return 0; 
} 

उत्तर

6

चाल निर्माता स्वचालित रूप से नहीं कहा जा जाएगा स्थानांतरित करने के लिए है इस मामले में, tmp एक लाभा है। आप एक rvalue संदर्भ के लिए यह कास्ट करने के लिए std::move उपयोग कर सकते हैं:

return std::make_tuple(std::move(tmp), 99); 

इस कदम से निर्माता का उपयोग करने के संकलक निर्देश देगा।

1

आप tmp चलती नहीं हैं:

A tmp(100); 

return std::make_tuple(std::move(tmp), 99); 
3

प्रतिलिपि return_two_non_reference_tuple() में जगह लेता है। इसे हटाने के लिए

एक तरीका है क्योंकि आप

std::make_tuple(tmp, 99); 

में बुला रहे हैं tmp

std::tuple<A, int> return_two_non_reference_tuple() 
{ 
    A tmp(100); 
    return std::make_tuple(std::move(tmp), 99); 
} 

या किसी अन्य तरीके से

std::tuple<A, int> return_two_non_reference_tuple() 
{ 
    return std::make_tuple(A(100), 99); 
} 
3

प्रति यहां होती है:

std::make_tuple(tmp, 99); 

यद्यपि आप देख सकते हैं कि tmp सीधे टपल में निर्माण किया जा करने में सक्षम हो सकता है, टपल को tmp से प्रति elided नहीं किया जाएगा। आप वास्तव में क्या चाहते हैं std::tuple के लिए अपने आंतरिक A और int ऑब्जेक्ट्स का निर्माण करने के लिए तर्कों को पारित करने का एक तरीका है। std::tuple के लिए ऐसी कोई चीज़ नहीं है, लेकिन एक ही प्रभाव प्राप्त करने का एक तरीका है।

चूंकि आपके पास केवल दो प्रकार हैं, आप std::pair का उपयोग कर सकते हैं। इसमें std::piecewise_construct कन्स्ट्रक्टर है, जो आंतरिक वस्तुओं के रचनाकारों को पास करने के लिए तर्कों को दो std::tuples लेता है।

std::pair<A, int> return_two_non_reference_tuple() 
{ 
    return {std::piecewise_construct, 
      std::make_tuple(100), std::make_tuple(99)}; 
} 

इस समाधान के बारे में अच्छी बात यह है कि आप अभी भी कॉल स्थल पर std::tie उपयोग कर सकते हैं, क्योंकि std::tuplestd::pair से एक असाइनमेंट ऑपरेटर है।

std::tie(t3, v1) = return_two_non_reference_tuple(); 

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

टेस्ट जोड़ी उत्पादन, non_reference टपल

डिफ़ॉल्ट निर्माता लागू

पैरामीटर निर्माता लागू

ले जाएँ असाइनमेंट ऑपरेटर ने

Live Demo

+0

धन्यवाद, यह साधारण मामले के लिए एक अच्छा विकल्प है, लेकिन यदि टीएमपी पर और अधिक क्रियाएं होती हैं, और अधिक आउटपुट, तो यह काम नहीं करेगा। और मुझे नहीं लगता कि यह एमएसवीसी 2012 में काम करेगा। – thorsan

+0

कॉपी एलिजन यहां हो रहा है। समस्या यह है कि 'tmp' को 'tuple' में नहीं ले जाया जा रहा है। कॉपी कन्स्ट्रक्टर 'tmp' को tuple में कॉपी करने से है, न कि कॉपी की प्रतिलिपि बनाई जा रही है। – Simple

+0

@ सिंपल मुझे पता है कि, शायद मेरा जवाब पर्याप्त स्पष्ट नहीं है। – TartanLlama