2014-08-29 11 views
19

में संदर्भ सदस्य के लिए अस्थायी बाध्यकारी के बारे में नकली चेतावनी मैं समझता हूं कि अगर अस्थायी निर्माता की प्रारंभिक सूची में संदर्भ सदस्य से बंधे हैं, तो ऑब्जेक्ट को कन्स्ट्रक्टर रिटर्न के रूप में नष्ट कर दिया जाएगा।कन्स्ट्रक्टर

हालांकि, निम्नलिखित कोड पर विचार करें:

#include <functional> 
#include <iostream> 

using callback_func = std::function<int(void)>; 

int 
func(const callback_func& callback) 
{ 
    struct wrapper 
    { 
    const callback_func& w_cb; 
    wrapper(const callback_func& cb) : w_cb {cb} { } 
    int call() { return this->w_cb() + this->w_cb(); } 
    }; 
    wrapper wrp {callback}; 
    return wrp.call(); 
} 

int 
main() 
{ 
    std::cout << func([](){ return 21; }) << std::endl; 
    return 0; 
} 

यह मेरे लिए पूरी तरह से वैध लग रहा है। callback ऑब्जेक्ट func फ़ंक्शन के पूरे निष्पादन के दौरान लाइव रहेगा और wrapper के निर्माता के लिए कोई अस्थायी प्रतिलिपि नहीं बनाई जानी चाहिए।

वास्तव में, जीसीसी 4.9.0 सभी चेतावनियों के साथ ठीक से संकलित करता है।

$ g++ -std=c++11 -W main.cpp 
main.cpp: In constructor ‘func(const callback_func&)::wrapper::wrapper(const callback_func&)’: 
main.cpp:12:48: warning: a temporary bound to ‘func(const callback_func&)::wrapper::w_cb’ only persists until the constructor exits [-Wextra] 
    wrapper(const callback_func& cb) : w_cb {cb} { } 
              ^

यह एक झूठी सकारात्मक है या मैं वस्तु जीवन काल गलतफहमी हूँ:

हालांकि, जीसीसी 4.8.2 संकलक मुझे निम्न चेतावनी देता है?

यहाँ मेरी सटीक संकलक संस्करणों का परीक्षण कर रहे हैं:

$ g++ --version 
g++ (GCC) 4.8.2 
Copyright (C) 2013 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
$ g++ --version 
g++ (GCC) 4.9.0 20140604 (prerelease) 
Copyright (C) 2014 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+0

ऑप्टिमाइज़ेशन को बंद करना मुझे एक सीजी गलती देता है। वेलग्रिंड बताते हैं कि समस्या कहीं आसपास 'समारोह (std :: समारोह स्थिरांक और) :: आवरण :: कॉल()' है। –

+2

'w_cb {cb}' का उपयोग करके मेरे लिए सेगमेंटेशन उल्लंघन में परिणाम। 'W_cb (cb)' का उपयोग करना एक ही समस्या से पीड़ित नहीं है। जी ++ 4.8.3 में परीक्षण किया गया। –

+0

मैं जीसीसी 4.8.2 के साथ वेलग्रिंड त्रुटि पुन: पेश कर सकते हैं। (नहीं एक segfault, कठिन, कार्यक्रम 42 आउटपुट और उम्मीद के रूप में सफलतापूर्वक बाहर निकालता है।) निष्पादन जीसीसी 4.9.0 द्वारा उत्पादित वेलग्रिंड-साफ है। ये अवलोकन विभिन्न अनुकूलन स्तरों के साथ नहीं बदलते हैं। – 5gon12eder

उत्तर

12

यह जीसीसी 4.8 में एक बग है कि 4.9 में तय किया गया है। यहाँ बग रिपोर्ट है:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50025

+1

तथ्य यह है कि बग * चेतावनी * नहीं है, बल्कि इसके बजाय * चेतावनी * आपको क्या चेतावनी दे रहा है, उपयोगी होगा। मुझे यह निर्धारित करने के लिए लिंक पर जाना पड़ा कि ... मैं, अस्थायी वास्तव में जीसीसी 4.8 में बनाया गया है और यह काफी देर तक नहीं टिकता है। अनुकूलन अस्थायी रूप से अस्तित्व से बाहर हो सकता है? – Yakk

+0

हां, यह बताता है कि क्या हो रहा है। लिंक के लिए धन्यवाद। मैंने इसके द्वारा प्रेरित कुछ और शोध किए और इसे उत्तर के रूप में पोस्ट करेंगे लेकिन मैं आपका स्वीकार करूंगा। – 5gon12eder

+4

यह मानक में एक बग था, और जीसीसी मानक के सटीक शब्द को कार्यान्वित कर रहा था, जो _required_ वहां बनाया जाने वाला अस्थायी है। डीआर 1288 मानक तय किया। –

5

के रूप में हावर्ड Hinnant द्वारा बताया और पहले से ही आर साहू की टिप्पणी ने संकेत दिया, यह एक बग (जो तब-टूट मानक के लिए आवश्यक हो के लिए इस्तेमाल किया है, टोनी डी करने के लिए धन्यवाद इस बात को इंगित करने के लिए) जिस तरह से जीसीसी 4.8 प्रारंभकर्ता सूचियों का इलाज कर रहा है।

wrapper(const callback_func& cb) : w_cb (cb) { } 

को

wrapper(const callback_func& cb) : w_cb {cb} { } 

से अपने मूल उदाहरण में निर्माता बदलने जीसीसी 4.8.3 के साथ चेतावनी चले जाओ और बनाया निष्पादन योग्य वेलग्रिंड स्वच्छ बनाता है। दो असेंबली फाइलों का अंतर बहुत बड़ा है इसलिए मैं इसे यहां पोस्ट नहीं करता हूं। जीसीसी 4.9.0 दोनों संस्करणों के लिए समान असेंबली कोड बनाता है।

इसके बाद, मैं एक उपयोगकर्ता परिभाषित struct और नष्ट कॉपी और चाल निर्माणकर्ता और असाइनमेंट ऑपरेटरों के साथ std::function बदल दिया। दरअसल, जीसीसी 4.8.3 के साथ, यह चेतावनी बरकरार रखता है लेकिन अब एक (थोड़ा और सहायक) त्रुटि भी देता है जो कोड की उपरोक्त पंक्ति संरचना के हटाए गए प्रतिलिपि निर्माता को कॉल करती है। जैसा कि अपेक्षित है, जीसीसी 4.9.0 के साथ कोई अंतर नहीं है।

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