2013-06-05 9 views
19

हाल ही में, मैंने अपने व्यवहार को समझने के लिए रावलों के साथ "खेला" है। अधिकांश नतीजे मुझे छेड़छाड़ नहीं करते थे, लेकिन फिर मैंने देखा कि अगर मैं स्थानीय चर फेंकता हूं, तो चालक कन्स्ट्रक्टर को बुलाया जाता है।क्यों स्थानीय परिवर्तनीय invokes चालक चालक फेंक?

तब तक, मैंने सोचा कि आंदोलन अर्थशास्त्र नियमों का उद्देश्य यह गारंटी देना है कि ऑब्जेक्ट स्थानांतरित हो जाएगा (और अमान्य हो जाएगा) अगर संकलक यह पता लगा सके कि इसका उपयोग अब और नहीं किया जाएगा (जैसे अस्थायी वस्तुओं में), या उपयोगकर्ता इसका वादा नहीं करता है (जैसा कि std :: move में)।

हालांकि, निम्न कोड में, इस शर्त में से कोई भी नहीं है, और मेरा चर अभी भी स्थानांतरित हो रहा है (कम से कम g ++ 4.7.3 पर)।

वह क्यों है?

#include <iostream> 
#include <string> 
using namespace std; 

int main() { 
    string s="blabla"; 
    try { 
     throw s; 
    } 
    catch(...) { 
     cout<<"Exception!\n"; 
    } 
    cout<<s; //prints nothing 
} 
+3

यदि ऐसा है, तो gcc में बग की तरह दिखता है। –

+0

@kbok: आप सही हैं, मैंने अपना जवाब हटा दिया है (इसलिए मैं यहां आपकी टिप्पणी का जवाब दे रहा हूं)।मैंने किसी भी तरह से 'कोशिश' ब्लॉक के अंदर घोषित किया था, सवाल को और सावधानी से पढ़ना चाहिए था। क्षमा करें सभी –

+0

कृपया इसे http://gcc.gnu.org/bugzilla पर रिपोर्ट करें - धन्यवाद! –

उत्तर

5

दिए गए मामले में, यह शायद एक कंपाइलर बग है, क्योंकि बाद में फेंक दिया गया चर (और स्थानांतरित) संदर्भित किया जाता है।

सामान्य मामले में throw पर चलने वाले सामान्य मामले में अवधारणात्मक रूप से return पर चलने जैसा ही है। जब यह ज्ञात हो जाता है कि परिवर्तनीय बिंदु (throw या return) के बाद परिवर्तनीय संदर्भित नहीं किया जा सकता है, तो स्वचालित रूप से चाल को स्वचालित रूप से संदर्भित करना अच्छा होता है।

+0

धन्यवाद। यह जानना हमेशा अच्छा होता है कि मेरा अंतर्ज्ञान जीसीसी से बेहतर है ... – asaelr

7

सी ++ मानक का कहना है (15.1.3):

फेंकने एक अपवाद कॉपी-initializes (8.5, 12.8) एक अस्थायी वस्तु, अपवाद वस्तु कहा जाता है। अस्थायी एक अंतराल है और मिलान करने वाले हैंडलर (15.3) में नामित चर को प्रारंभ करने के लिए प्रयोग किया जाता है।

इस पैरा भी यहाँ प्रासंगिक हो सकता है (12.8.31):

कुछ मानदंड पूरे कर रहे हैं, एक कार्यान्वयन एक वर्ग वस्तु की कॉपी/कदम निर्माण छोड़ करने की अनुमति दी है, भले ही निर्माता चयनित कॉपी/मूव ऑपरेशन और/या ऑब्जेक्ट के लिए विनाशक के दुष्प्रभाव हैं। ऐसे मामलों में, कार्यान्वयन किसी भी वस्तु का संदर्भ देने के दो अलग-अलग तरीकों के रूप में छोड़े गए प्रतिलिपि/चालन संचालन के स्रोत और लक्ष्य का व्यवहार करता है, और उस वस्तु का विनाश उस समय के बाद होता है जब दोनों वस्तुओं के पास होता अनुकूलन के बिना नष्ट कर दिया गया है। कॉपी/कदम आपरेशन के इस इलिजन, कॉपी इलिजन कहा जाता है, (जो कई प्रतियां खत्म करने के लिए जोड़ा जा सकता है) निम्नलिखित परिस्थितियों में अनुमति दी है:

(...)

- एक थ्रो-अभिव्यक्ति में , जब ऑपरेंड एक गैर-अस्थिर स्वचालित ऑब्जेक्ट का नाम होता है (फ़ंक्शन या कैच-क्लॉज पैरामीटर के अलावा) जिसका दायरा आंतरिक संलग्नक-प्रयास (यदि कोई है तो) के अंत से आगे नहीं बढ़ता है, ऑपरेंड से अपवाद ऑब्जेक्ट (15.1) में कॉपी/मूव ऑपरेशन स्वचालित ऑब्जेक्ट को सीधे अपवाद ऑब्जेक्ट
में छोड़कर छोड़ा जा सकता है

विजुअल स्टूडियो 2012 में जांच की गई, प्रभाव:

Exception! 
blabla 

यह जीसीसी में एक बग वास्तव में की तरह दिखता है।

+0

यदि ऐसा है, तो 'फेंक' 'try' ब्लॉक के अंदर नहीं होने पर भी कंपाइलर को कन्स्ट्रक्टर को कॉल करने की अनुमति नहीं है? – asaelr

+0

@asaelr: अद्यतन उद्धरण से ऐसा लगता है कि फेंकने वाली वस्तु को कॉपी, स्थानांतरित या यहां तक ​​कि निर्माण में भी बनाया जा सकता है - वापसी मूल्य के लिए। –

+0

@asaelr यह है। लेकिन इस विशेष मामले में यह move-ctor को गलत तरीके से कॉल करता है, क्योंकि चर को बाद में try-block से बाहर किया जाता है। – Spook

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