क्यों अप्रयुक्त वापसी मूल्यों को शून्य करने के लिए?


112
int fn();

void whatever()
{
    (void) fn();
}

क्या किसी अप्रयुक्त वापसी मूल्य को शून्य करने का कोई कारण है, या क्या मैं यह सोचने में सही हूं कि यह समय की पूरी बर्बादी है?

ऊपर का पालन करें:

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

अगर बग की वजह से बच जाता है तो मैं अपने शब्दों को खाऊंगा ...

जवाबों:


79

डेविड का जवाब बहुत अधिक इसके लिए प्रेरणा को शामिल करता है, अन्य "डेवलपर्स" को स्पष्ट रूप से दिखाने के लिए कि आप इस फ़ंक्शन को जानते हैं लेकिन आप इसे स्पष्ट रूप से अनदेखा कर रहे हैं।

यह सुनिश्चित करने का एक तरीका है कि जहां आवश्यक त्रुटि कोड हमेशा संभाले जाते हैं।

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

class A {};
A operator+(A const &, A const &);

int main () {
  A a;
  a + a;                 // Not a problem
  (void)operator+(a,a);  // Using function call notation - so add the cast.

यह एकमात्र स्थान है जिसे मैं सी-स्टाइल कास्ट भी पसंद करता हूं। मेरे कोडिंग मानक में, मैं "v a" में जोड़ दूंगा (शून्य) भी (उचित रूप से, निश्चित रूप से: पी)
जोहान्स स्काउब -

8
विषय से थोड़ा हटकर, लेकिन कभी आप "a + a" क्यों करेंगे? वापसी मूल्य का उपयोग किए बिना उस तरह? यह वास्तव में मेरे लिए साइड इफेक्ट्स के दुरुपयोग की तरह लगता है, और कोड के इरादे को बाधित करता है।
रोब के

5
ठीक है, जो आप हर दिन उपयोग करेंगे वह 'a = a' होगा। यह ऑब्जेक्ट को सौंपे गए रिटर्न (सभी अच्छी तरह से व्यवहार करने वाले वर्गों के लिए है! :))। एक और उदाहरण है: ओएस << "हैलो वर्ल्ड" << std :: endl। उनमें से प्रत्येक "ओएस" वस्तु लौटाता है।
कॉर्ड में रिचर्ड कॉर्डन

46

काम में हम यह मानने के लिए उपयोग करते हैं कि फ़ंक्शन का रिटर्न मान है लेकिन डेवलपर ने दावा किया है कि इसे अनदेखा करना सुरक्षित है। चूंकि आपने C ++ के रूप में प्रश्न को टैग किया था, इसलिए आपको static_cast का उपयोग करना चाहिए :

static_cast<void>(fn());

जहाँ तक संकलक को वापस जाने के मूल्य को शून्य करने के लिए जाता है, इसका बहुत कम अर्थ है।


क्या यह अप्रयुक्त वापसी मूल्यों के बारे में चेतावनी को दबा देता है?
पॉल टॉम्बलिन

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

2
मैं g ++ का उपयोग करता हूं और यह ऐसे कलाकारों के साथ चेतावनी भी देता है।
13

2
आप किस चेतावनी के विकल्प का उपयोग करते हैं? -उपयोग-मूल्य मेरे वातावरण में चेतावनी को ट्रिगर नहीं करता है
Mykola Golubyev

VC ++ में, यह चेतावनी को दबा देता है
jalf

39

इस कोड को करने का सही कारण C कोड पर प्रयुक्त टूल है, जिसे लिंट कहा जाता है ।

यह संभावित समस्याओं की तलाश में कोड का विश्लेषण करता है और चेतावनी और सुझाव जारी करता है। यदि कोई फ़ंक्शन ऐसा मान लौटाता है जिसे तब चेक नहीं किया गया था, तो lintयह आकस्मिक होने पर चेतावनी देगा। lintइस चेतावनी पर चुप्पी साधने के लिए, आपने कॉल को कॉल किया (void)


2
यह इस तरह से शुरू हो सकता है, लेकिन अधिकांश उपकरणों में इस तरह की चेतावनी को दबाने के लिए अब अन्य तंत्र हैं। इसके अलावा - भले ही यह क्यों शुरू हुआ, विशेष रूप से सुरक्षा महत्वपूर्ण कोड के क्षेत्र के भीतर, यह "सामान्य" दस्तावेज़ इरादों का सामान्य तरीका बन गया है।
रिचर्ड कॉर्डन

5
जीसीसी इसके लिए एक चेतावनी देता है -Wall के साथ।
ग्रेफेड

23

कास्टिंग voidका उपयोग अप्रयुक्त चर और सहेजे गए वापसी मूल्यों या अभिव्यक्तियों के लिए संकलक चेतावनी को दबाने के लिए किया जाता है।

मानक (2003) Standard5.2.9 / 4 में कहता है,

किसी भी अभिव्यक्ति को स्पष्ट रूप से "cv शून्य" प्रकार में परिवर्तित किया जा सकता है। अभिव्यक्ति मान को छोड़ दिया गया है

तो आप लिख सकते हैं:

//suppressing unused variable warnings
static_cast<void>(unusedVar);
static_cast<const void>(unusedVar);
static_cast<volatile void>(unusedVar);

//suppressing return value warnings
static_cast<void>(fn());
static_cast<const void>(fn());
static_cast<volatile void>(fn());

//suppressing unsaved expressions
static_cast<void>(a + b * 10);
static_cast<const void>( x &&y || z);
static_cast<volatile void>( m | n + fn());

सभी फॉर्म वैध हैं। मैं आमतौर पर इसे छोटा बनाता हूं:

//suppressing  expressions
(void)(unusedVar);
(void)(fn());
(void)(x &&y || z);

इसकी भी ठीक है।


1
सिवाय इसके कि यह हमेशा संकलक चेतावनी को बंद नहीं करता है। gcc शून्य पर कास्टिंग का जवाब नहीं लगता है
Matt

@ मैट: जीसीसी के कौन से संस्करण का उपयोग कर रहे हैं? क्या आप अपना कोड ideone.com या stacked-crooked.com पर पोस्ट कर सकते हैं (बाद वाला बेहतर है)।
नवाज

1
क्या मानक "खारिज" शब्द का अर्थ है कि चेतावनी को लिंटर द्वारा नहीं उठाया जाना चाहिए?
सिरो सेंटिल्ली 郝海东 i iro i 法轮功 '

2
@CiroSantilli 巴拿馬 文件 事件 法轮功 ....: .... यह एक दिलचस्प सवाल है। वर्तमान में, मुझे इसका उत्तर नहीं पता है। अगर आपको इसकी जानकारी मिलती है तो कृपया मेरे साथ साझा करें।
नवाज

8

C ++ 17 के बाद से हमारे पास वह [[maybe_unused]]विशेषता है जिसका उपयोग voidकलाकारों के बजाय किया जा सकता है ।


1
C ++ 17 भी जोड़ा गया है nodiscardजो ब्याज की हो सकती है: stackoverflow.com/a/61675726/895245 इसके अलावा, मुझे लगता है कि आप [[maybe_unused]]सीधे उस कॉल पर लागू नहीं कर सकते जो ऐसा लगता है, केवल एक डमी वैरिएबल पर जो कॉल की वापसी को स्वीकार करता है? अगर यह सही है तो यह थोड़ा मुश्किल है।
सिरो सेंटिल्ली i i i i i i

4

शून्य से कास्ट करना महंगा है। यह केवल संकलक के लिए जानकारी है कि इसका इलाज कैसे किया जाए।


1
यह "महंगा" है अगर इसे लिखने का समय और बाद में पढ़ने, समझने (और फिर अनदेखी) कोड मुक्त है। IMO, लेखन (void)मुझे समय और ऊर्जा खर्च करता है और मुझे आश्चर्य होता है कि क्या लेखक जानता था कि अभिव्यक्ति कैसे काम करती है।
21-22 बजे

4

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


2
यह दूसरों को स्पष्ट रूप से बताने के लिए एक ज्ञात पैटर्न है कि आप वापसी मूल्य के बारे में परवाह नहीं करते हैं, कि आप इसे संभालना नहीं भूले।
Spidey

For the functionality of you program casting to void is meaninglessआत्म-प्रलेखन और संकलन करते समय चेतावनी की संख्या के लिए, यह वास्तव में नहीं है। you should not use it to signal something to the person that is reading the code [...] it is better to use a comment.सबसे अच्छी टिप्पणी कोई टिप्पणी नहीं है , जब कोड खुद को समझाता है। और, फिर से, प्रक्रिया में एक खुश चेतावनी संकलक को खुश रखता है।
अंडरस्कोर_ड

'इस तरह एक कलाकार को जोड़ना केवल अजीब लगेगा और संभावित कारण के बारे में सवाल उठाएगा'। मैंने इनमें से एक की खोज की, और इसलिए मैं इसे पढ़ रहा हूं। मेरे अप्रशिक्षित मस्तिष्क के लिए रहस्यमय स्टैक-दुरुपयोग की तरह लगता है।
mynameisnafe

1

इसके अलावा जब आपका कोड MISTA (या अन्य) मानकों का अनुपालन करता है, तो एलडीआरए जैसे स्वचालित उपकरण आपको एक फ़ंक्शन को कॉल करने की अनुमति नहीं देंगे, जिसमें एक वापसी प्रकार होता है, जब तक कि यह एक मूल्य वापस नहीं करता है जब तक कि आप स्पष्ट रूप से दिए गए मान को नहीं डालते (शून्य)


0

सी ++ 17 [[nodiscard]]

सी ++ 17 ने एक विशेषता के साथ "वापसी मूल्य की अनदेखी व्यापार" को मानकीकृत किया।

इसलिए, मुझे आशा है कि अनुपालन कार्यान्वयन हमेशा तभी चेतावनी देंगे जब nodiscard दिया दिया जाएगा, और अन्यथा कभी भी चेतावनी नहीं दी जाएगी।

उदाहरण:

main.cpp

[[nodiscard]] int f() {
    return 1;
}

int main() {
    f();
}

संकलन:

g++ -std=c++17 -ggdb3 -O0 -Wall -Wextra -pedantic -o main.out main.cpp

परिणाम:

main.cpp: In function int main()’:
main.cpp:6:6: warning: ignoring return value of int f()’, declared with attribute nodiscard [-Wunused-result]
    6 |     f();
      |     ~^~
main.cpp:1:19: note: declared here
    1 | [[nodiscard]] int f() {
      | 

निम्नलिखित सभी चेतावनी से बचें:

(void)f();
[[maybe_unused]] int i = f();

मैं maybe_unusedसीधे f()कॉल पर उपयोग करने में सक्षम नहीं था :

[[maybe_unused]] f();

देता है:

main.cpp: In function int main()’:
main.cpp:6:5: warning: attributes at the beginning of statement are ignored [-Wattributes]
    6 |     [[maybe_unused]] f();
      |     ^~~~~~~~~~~~~~~~

(void)डाली काम कर अनिवार्य होना प्रतीत नहीं होता है, लेकिन "प्रोत्साहित" है मानक में: कैसे मैं जानबूझकर एक [[nodiscard]] वापसी मान त्यागने कर सकते हैं?

चेतावनी संदेश से भी देखा जा सकता है, चेतावनी के लिए एक "समाधान" जोड़ना है -Wno-unused-result:

g++ -std=c++17 -ggdb3 -O0 -Wall -Wextra -pedantic -Wno-unused-result -o main.out main.cpp

हालांकि मैं निश्चित रूप से इस तरह से विश्व स्तर पर चेतावनियों को नजरअंदाज करने की सलाह नहीं देता।

सी ++ 20 भी आप के लिए एक कारण जोड़ने की अनुमति देता nodiscardमें के रूप में [[nodiscard("reason")]]के रूप में उल्लेख किया https://en.cppreference.com/w/cpp/language/attributes/nodiscard

जीसीसी warn_unused_result विशेषता

के मानकीकरण से पहले [[nodiscard]], और सी के लिए इससे पहले कि वे अंततः विशेषताओं को मानकीकृत करने का निर्णय लेते हैं, जीसीसी ने ठीक उसी कार्यक्षमता के साथ लागू किया warn_unused_result:

int f() __attribute__ ((warn_unused_result));

int f() {
    return 1;
}

int main() {
    f();
}

जो देता है:

main.cpp: In function int main()’:
main.cpp:8:6: warning: ignoring return value of int f()’, declared with attribute warn_unused_result [-Wunused-result]
    8 |     f();
      |     ~^~

तब यह ध्यान दिया जाना चाहिए कि चूंकि एएनएसआई सी के पास इसके लिए कोई मानक नहीं है, एएनएसआई सी यह निर्दिष्ट नहीं करता है कि सी मानक पुस्तकालय कार्यों में कौन सी विशेषता है या नहीं और इसलिए कार्यान्वयन ने अपने स्वयं के निर्णय किए हैं कि क्या होना चाहिए या नहीं के साथ चिह्नित किया जाना चाहिए warn_unuesd_result, जो यही कारण है कि सामान्य तौर पर आपको (void)किसी भी कार्यान्वयन में चेतावनी से पूरी तरह से बचने के लिए मानक पुस्तकालय कार्यों के लिए किसी भी कॉल के रिटर्न को अनदेखा करने के लिए कलाकारों का उपयोग करना होगा ।

GCC 9.2.1, उबंटू 19.10 में परीक्षण किया गया।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.