2008-10-20 6 views
13

विजुअल स्टूडियो में, मैं अक्सर आरएआईआई उद्देश्यों के लिए वस्तुओं का उपयोग करता हूं। उदाहरण के लिए:स्कोप हेल्पर्स के विनाश के लिए सी ++ "प्रारंभिक लेकिन संदर्भित नहीं" चेतावनी से निपटना?

ScopeGuard close_guard = MakeGuard(&close_file, file); 

close_guard का पूरा उद्देश्य है, यह कहीं और नहीं किया जाता है सुनिश्चित करें कि फ़ाइल समारोह बाहर निकलने पर करीब होगा बनाना है। हालांकि, विजुअल स्टूडियो मुझे एक चेतावनी देता है कि "स्थानीय चर प्रारंभ किया गया है लेकिन संदर्भित नहीं है"। मैं इस विशिष्ट मामले के लिए इस चेतावनी को बंद करना चाहता हूं।

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

मैं #pragma चेतावनी इस के लिए निर्देश का उपयोग नहीं करना चाहता क्योंकि यह वैध कारणों से भी इस चेतावनी को बंद कर देगा।

+0

क्या आप स्कोपगार्ड और मेकगार्ड (या कुछ कट-डाउन संस्करणों के लिए कोड पोस्ट कर सकते हैं जो अभी भी व्यवहार प्रदर्शित करते हैं)? –

+0

कृपया एक संभावित कार्यान्वयन के लिए http://www.ddj.com/cpp/184403758 पढ़ें। –

+0

एमएसवीसी का कौन सा संस्करण आप इस व्यवहार को देख रहे हैं? – MSN

उत्तर

5

विधि 1:#pragma warning निर्देश का उपयोग करें।

#pragma warning कंपाइलर चेतावनी संदेशों के व्यवहार के चुनिंदा संशोधन की अनुमति देता है।

#pragma warning(push) 
#pragma warning(disable : 4705) // replace 4705 with warning number 

ScopeGuard close_guard = MakeGuard(&close_file, file); 

#pragma warning(pop) 

इस कोड को वर्तमान चेतावनी राज्य की बचत होती है, तो यह एक विशिष्ट चेतावनी कोड के लिए चेतावनी को निष्क्रिय और फिर सहेजा गया अंतिम चेतावनी राज्य पुनर्स्थापित करता है।

विधि 2: निम्न की तरह एक कार्यवाही का उपयोग करें। विजुअल स्टूडियो खुश होगा और आप भी करेंगे। यह कामकाज कई माइक्रोसॉफ्ट नमूने और अन्य परियोजनाओं में भी प्रयोग किया जाता है।

ScopeGuard close_guard = MakeGuard(&close_file, file); 
close_guard; 

या आप चेतावनी को हल करने के लिए #define बना सकते हैं।

#define UNUSED_VAR(VAR) VAR 
... 
ScopeGuard close_guard = MakeGuard(&close_file, file); 
UNUSED_VAR(close_guard); 

कुछ उपयोगकर्ताओं ने कहा कि प्रस्तुत कोड काम नहीं करेगा क्योंकि ScopeGuard एक typedef है। यह धारणा गलत है।

http://www.ddj.com/cpp/184403758

सी ++ मानक के अनुसार, एक संदर्भ एक अस्थायी मूल्य के साथ प्रारंभ करता है कि अस्थायी मूल्य संदर्भ के ही जीवन भर के लिए लाइव ।

+0

यह एंड्री अलेक्जेंड्रेस्कु और पेट्रू मार्जिनन द्वारा [डॉबब के जर्नल] (http://www.ddj.com/cpp/184403758) में पोस्ट किया गया था। ये मजबूत पृष्ठभूमि वाले दो सी ++ खिलाड़ी हैं। और मैंने कभी ऐसा व्यवहार नहीं किया है। इसे जांच लेंगे और बाद में टिप्पणी करेंगे। –

+0

स्कोपगार्ड वास्तव में संदर्भ प्रकार के लिए टाइपिफ़ है, लेकिन यह गलत नहीं है। सिंक के लिंक से उद्धरण: "सी ++ मानक के अनुसार, एक अस्थायी मूल्य के साथ शुरू किया गया संदर्भ बनाता है कि अस्थायी मूल्य संदर्भ के जीवनकाल के लिए ही रहता है।" –

+0

हां यह लेख में महत्वपूर्ण हिस्सा है जो तंत्र को काम करता है। तथ्य यह है कि स्कोपगार्ड एक टाइपिफ़ है, कोड को गलत नहीं बनाता है और यह अभी भी काम करता है। यहां तक ​​कि अगर ऐसा होता तो हम एक और पूर्ण विषय पर बहस करेंगे, सवाल नहीं। –

0

स्कोपगार्ड घोषणा में 'अस्थिर' जोड़ने का प्रयास करें।

+0

वह क्या करेगा? –

+0

शायद इस मामले में कुछ भी नहीं, सिवाय इसके कि संकलक चेतावनी चुप हो। – Aaron

+0

अस्थिरता संकलक को बताती है कि चर को इसके ज्ञान के बाहर बदला जा सकता है। मैं इसे हार्डवेयर रजिस्टरों के लिए बहुत उपयोग करता हूं। यदि चर अस्थिर है, तो कंपाइलर को इसे बनाना और इसे असाइन करना होगा। – Robert

3

हम का उपयोग करें:

static_cast<void>(close_guard); 

चर कि संकलक के बारे में शिकायत कर रहा है के लिए।

+0

मैं कहूंगा कि शून्य को कास्टिंग संभवतः एक ऐसी स्थिति है जहां सी-स्टाइल कास्ट एक static_cast पर सी ++ में उचित है ... –

1

आप गुंजाइश कोड की है कि रेखा के आसपास #pragma चेतावनी केवल

#pragma warning(push) 
#pragma warning(disable:XXXX) 
your code here; 
#pragma warning(pop) 

या

#pragma warning(disable:XXXX) 
your code here; 
#pragma warning(default:XXXX) 

का उपयोग करके आपको ऊपर कोड की पंक्ति के बाद UNREFERENCED_PARAMETER(close_guard); उपयोग कर सकते हैं।

ScopeGuard close_guard = MakeGuard(&close_file, file); 
UNUSED(close_guard); 

कौन सा चेतावनी चुप्पी, और यह दस्तावेज:

#define UNUSED(x) x 

की तरह इस्तेमाल किया:

3

कुलपति ++ हेडर फाइल में से कुछ में, एमएस एक मैक्रो परिभाषित करता है।

+0

UNUSED_ALWAYS को अधिकांश विंडोज प्रोग्राम में भी परिभाषित किया गया है, और उसी तरह काम करता है। –

8

यदि आपके ऑब्जेक्ट में एक गैर-तुच्छ विनाशक है, तो विजुअल स्टूडियो आपको यह चेतावनी दे रहा है। निम्नलिखित कोड चेतावनी के साथ VS2005 में कोई चेतावनी उत्पन्न नहीं करता है नीचे से ऊपर तक (/ W4) कर दिया:


class Test 
{ 
public: 
    ~Test(void) { printf("destructor\n"); } 
}; 

Test foo(void) { return Test(); } 

int main(void) 
{ 
    Test t = foo(); 
    printf("moo\n"); 

    return 0; 
} 

नाशक बाहर टिप्पणी करते हुए एक चेतावनी देता है; कोड के रूप में नहीं है।

+0

समस्या यह प्रतीत होती है कि 'स्कोपगार्ड' वास्तव में एक गैर-तुच्छ विनाशक के साथ किसी ऑब्जेक्ट के लिए एक संदर्भ टाइपपीफ है। वीएस इस सही तरीके से निपटने के लिए 'स्मार्ट पर्याप्त' प्रतीत नहीं होता है। –

0

मैं ऊपर smink पद का उपयोग करें और जोड़ने के लिए है कि मैं एक टिप्पणी अगले #define से चिपके कह // दृश्य स्टूडियो में चेतावनी [चेतावनी संख्या]

-3

मुख्य मुद्दा यहाँ वास्तव में हो रहा है को दबाने के लिए इस्तेमाल किया ही है कि कंपाइलर यह समझ में नहीं आता है कि आप क्या कर रहे हैं ... जो सी ++ में स्कोपिंग सेमेन्टिक्स का उपयोग करने के लिए प्रतीत होता है, जिसे कुछ कोड कहा जाता है जब एक चर का उपयोग नहीं किया जाता है, तब भी इसका उपयोग नहीं किया जाता है। सही? वह तंत्र स्वयं मुझे सीमा रेखा के रूप में मारता है ... एक कंपाइलर को अप्रयुक्त चर को हटाने का अधिकार होना चाहिए, लेकिन सी ++ निर्माण अर्थशास्त्र वास्तव में इन चीजों को गड़बड़ कर देता है। ऐसा करने का कोई और तरीका नहीं है जो कम से कम हाथ से है?

+1

आरएआईआई एक शक्तिशाली तकनीक है। आपको वास्तव में http://www.ddj.com/cpp/184403758 –

+0

पढ़ने पर विचार करना चाहिए, यह बहुत दिलचस्प था। लेकिन वहां, वे ".dismiss()" कॉल में बनाए गए ऑब्जेक्ट तक पहुंचने लगते हैं जो इसे इस्तेमाल करने के लिए प्रतीत होता है? तो वीसी संकलक तब शिकायत करेंगे? – jakobengblom2

+0

यदि आप ".dismiss()" फ़ंक्शन का उपयोग करते हैं, तो यह शिकायत नहीं करेगा। लेकिन यह मामला यहां नहीं है;) –

2

ठीक है, इस मामले में स्कोपगार्ड वास्तव में संदर्भ प्रकार के लिए टाइपिफ़ है। यह दुर्भाग्य से काम नहीं करेगा।

इसका मतलब यह नहीं होगा कि पूरा स्कोपगार्ड काम नहीं करता है, क्योंकि उस मामले में विनाशक को नहीं बुलाया जाएगा ???

+0

यदि कोई सोच रहा है कि कहां से आया है। ओपी द्वारा 'शेरम पेंडले' के जवाब पर यह एक टिप्पणी थी जिसे हटा दिया गया था। मुझे लगता है कि शेरम ने इसे हटा दिया क्योंकि टिप्पणी ने सुझाव दिया कि उसका समाधान उपयोग योग्य नहीं होगा। –

+0

नहीं, मेरा मतलब था कि इसका उपयोग करने से पहले चर घोषित करना काम नहीं करेगा क्योंकि यह वास्तव में एक संदर्भ है। –

+0

दरअसल, यह ठीक है ... अस्थायी के संदर्भ को बाध्य करने से संदर्भ के लिए अस्थायी जीवनकाल बढ़ जाता है। उदाहरण: {स्ट्रिंग और एस = स्ट्रिंग ("हैलो") + "दुनिया!"; cout << एस; } यह कोड ठीक है, क्योंकि ऑपरेटर द्वारा अस्थायी लौटाया गया + अगली बंद ब्रेस तक रहता है। – Aaron

1

मुझे लगता है कि अभ्यास में, मैं बदसूरत रूप से #pragma अक्षम ... या 'UNUSED' के साथ जाऊंगा। हालांकि, एक मुख्य नियम के रूप में, कोड को कुछ अतिरिक्त थोक की कीमत पर भी चेतावनियों से साफ रखा जाना चाहिए। इसे बिना किसी चेतावनी के विभिन्न प्लेटफार्मों और ऑपरेटिंग सिस्टम पर कई अलग-अलग कंपाइलरों में संकलित करना चाहिए। यदि ऐसा नहीं होता है, तो कोड को ठीक करना होगा ताकि यह किया जा सके। जीसीसी-चेतावनी स्तर पर चेतावनियां उत्पन्न करने वाले कोड को बनाए रखना एक अच्छा विचार नहीं है।

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

+0

यह कंपाइलर चेतावनी pedantic है। इसे सीधे अक्षम करें। यह मामलों में स्वयं दस्तावेज़ कोड को नुकसान पहुंचाता है, पूर्व: शून्य foo (int/* numberOfWidgets * /); – Aaron

0

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

3

मैं इस मामले में सभी तरह से मैक्रो का उपयोग करेंगे:

#define SCOPE_GUARD(guard, fn, param) \ 
    ScopeGuard guard = MakeGuard(fn, param); \ 
    static_cast<void>(guard) 

अब अपनी कोड अच्छा और छोटा है:

इस दृष्टिकोण का
SCOPE_GUARD(g1, &file_close, file1); 
SCOPE_GUARD(g2, &file_close, file2); 

लाभ यह है कि अगर बाद में आप जोड़ सकते हैं __LINE__, __func__ आदि यदि आवश्यक हो तो गार्ड कार्रवाई को लॉग इन करने के लिए।

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