बूलियन्स के लिए c ++ में && = या = = क्यों नहीं है?


126

क्या एक "बहुत खराब चीज" है जो हो सकती है &&=और ||=इसके लिए सिंटैक्टिक चीनी के रूप में उपयोग किया जाता है bool foo = foo && barऔर bool foo = foo || bar?


5
यह अन्य प्रश्न देखें: stackoverflow.com/questions/2324549/… यह जावा के बारे में है, लेकिन C वंश को साझा करते हुए, वही तर्क अधिकतर लागू होते हैं।
जेम्सडलिन

असल में, सिर्फ c ++ में b / c नहीं है, उन्होंने इसे अंदर नहीं डाला है - रूबी जैसी भाषाओं में यह है। बू ...
काच

2
लेकिन रूबी में, किसी भी प्रकार के लिए x ||= yC ++ के बराबर नहीं है x = x ? x : y;? दूसरे शब्दों में, "पहले से सेट नहीं है तो y पर सेट करें"। यह C या C ++ की तुलना में बहुत अधिक उपयोगी है x ||= y, जो (ओवरलोडिंग ऑपरेटर को रोकना) "x को (bool)yतब तक सेट करेगा जब तक कि पहले से सेट न हो जाए"। मैं इसके लिए एक और ऑपरेटर जोड़ने के लिए उत्सुक नहीं हूं, यह थोड़ा कमज़ोर लगता है। बस लिखो if (!x) x = (bool)y। लेकिन फिर भी, मैं वास्तव में boolअतिरिक्त ऑपरेटरों को प्राप्त करने के लिए चर का उपयोग नहीं करता हूं जो केवल उस एक प्रकार के साथ वास्तव में उपयोगी हैं।
स्टीव जेसोप

1
मुझे यकीन है कि C ++ का प्राथमिक कारण नहीं है &&=या ||=बस इतना है कि C उनके पास नहीं है। मुझे यकीन है कि कारण सी उनके पास नहीं है कि कार्यक्षमता को पर्याप्त रूप से लाभप्रद नहीं माना गया है।
जोनाथन लेफलर

2
इसके अलावा, अति-पांडित्यपूर्ण होने के कारण, यह अंकन bool foo = foo || bar;अपरिभाषित व्यवहार का आह्वान करता है क्योंकि fooइसके मूल्यांकन से पहले इसे प्रारंभ नहीं किया जाता है foo || bar। बेशक, यह कुछ इस तरह का है bool foo = …initialization…; …; foo = foo || bar;और सवाल फिर वैध है।
जोनाथन लेफलर

जवाबों:


73

A boolकेवल trueया falseC ++ में हो सकता है। इस तरह, का उपयोग करना &=और |=अपेक्षाकृत सुरक्षित है (भले ही मैं विशेष रूप से संकेतन पसंद नहीं करता)। सच है, वे तार्किक संचालन के बजाय बिट संचालन करेंगे (और इस तरह वे शॉर्ट-सर्किट नहीं करेंगे) लेकिन ये बिट ऑपरेशन एक अच्छी तरह से परिभाषित मानचित्रण का पालन करते हैं, जो प्रभावी रूप से तार्किक संचालन के बराबर है, जब तक कि दोनों ऑपरेंड प्रकार के होते हैंbool1

अन्य लोगों ने यहां जो कहा है, उसके विपरीत, boolC ++ में कभी भी अलग मूल्य नहीं होना चाहिए जैसे कि 2। जब उस मान को a को असाइन किया जाता है bool, तो इसे trueमानक के अनुसार रूपांतरित किया जाएगा ।

पॉइंटर्स boolका उपयोग करके एक अमान्य मान प्राप्त करने का एकमात्र तरीका है reinterpret_cast:

int i = 2;
bool b = *reinterpret_cast<bool*>(&i);
b |= true; // MAY yield 3 (but doesn’t on my PC!)

लेकिन चूंकि इस कोड का अपरिभाषित व्यवहार होता है, इसलिए हम C ++ कोड के अनुरूप इस संभावित समस्या को सुरक्षित रूप से अनदेखा कर सकते हैं।


1 मोटे तौर पर यह एगेव की टिप्पणी के रूप में एक बड़ा चेतावनी है:

bool b = true;
b &= 2; // yields `false`.

कारण यह है कि b & 2पूर्णांक पदोन्नति ऐसा करता है कि अभिव्यक्ति तब के बराबर होती है static_cast<int>(b) & 2, जिसके परिणामस्वरूप 0, जो तब वापस एक में परिवर्तित हो जाता है bool। तो यह सच है कि एक के अस्तित्व operator &&=प्रकार सुरक्षा में सुधार होगा।


4
लेकिन && और || ऑपरेटर किसी भी चीज़ पर काम करेंगे जो बूल में परिवर्तित होती है, न कि केवल बूल में।
dan04

13
वे एक ही काम नहीं करते हैं, यहां तक ​​कि बूल पर भी। ||और &&शॉर्टकट, यानी दूसरा तर्क ऑपरेंड नहीं है यदि पहला ऑपरेंड true(सम्मान के falseलिए &&) है। |, &, |=और &=हमेशा दोनों ऑपरेंड का मूल्यांकन।
निकी

4
यह इस सवाल का जवाब नहीं देता कि क्यों && = और = = c ++ ऑपरेटर नहीं हैं।
थान

9
यह नहीं उपयोग करने के लिए सुरक्षित &=प्रकार का एक बाएं ओर के लिए boolहै, क्योंकि यह पूरी तरह से संभव है के लिए दाएँ हाथ की ओर के अलावा अन्य प्रकार की होनी चाहिए bool(जैसे islowerया किसी अन्य सी stdlib समारोह जो सच मूल्य के लिए अशून्य रिटर्न)। यदि हमारे पास काल्पनिक है &&=, तो संभवत: यह दाहिने हाथ को बदलने के लिए मजबूर करेगा bool, जो &=नहीं करता है। दूसरे शब्दों में, bool b = true; b &= 2;परिणाम b == false
Angew अब SO

2
@ एंटोनियो कठिन भीड़। Rud
कोनराड रूडोल्फ

44

&&और &अलग शब्दार्थ है: &&दूसरे ऑपरेंड का मूल्यांकन नहीं करेंगे यदि पहला ऑपरेंड है false। जैसे कुछ

flag = (ptr != NULL) && (ptr->member > 3);

सुरक्षित है, लेकिन

flag = (ptr != NULL) & (ptr->member > 3);

हालांकि, दोनों ऑपरेंड प्रकार के नहीं हैं bool

उसी के लिए सच है &=और |=:

flag = CheckFileExists();
flag = flag && CheckFileReadable();
flag = flag && CheckFileContents();

इससे अलग व्यवहार करेगा:

flag = CheckFileExists();
flag &= CheckFileReadable();
flag &= CheckFileContents();

35
मेरी राय में && = होने के सभी और कारण। = पी
काच

4
हालांकि यह वास्तव में एक जवाब नहीं है।
कैत्स्कुल

27

संक्षिप्त जवाब

सभी ऑपरेटरों +=, -=, *=, /=, &=, |=... गणित कर रहे हैं और एक ही उम्मीद प्रदान करते हैं:

x &= foo()  // We expect foo() be called whatever the value of x

हालांकि, ऑपरेटरों &&=और ||=तार्किक होगा, और इन ऑपरेटरों त्रुटि प्रवण क्योंकि कई डेवलपर्स उम्मीद करेंगे हो सकता है foo()हमेशा में कहा जा x &&= foo()

bool x;
// ...
x &&= foo();           // Many developers might be confused
x = x && foo();        // Still confusing but correct
x = x ? foo() : x;     // Understandable
x = x ? foo() : false; // Understandable
if (x) x = foo();      // Obvious
  • क्या वास्तव में हमें शॉर्टकट पाने के लिए C / C ++ को और अधिक जटिल बनाने की आवश्यकता है x = x && foo()?

  • क्या हम वास्तव में अधिक गूढ़ कथन को बाधित करना चाहते हैं x = x && foo()?
    या हम सार्थक कोड लिखना चाहते हैं if (x) x = foo();?


लंबा जवाब

के लिए उदाहरण &&=

यदि &&=ऑपरेटर उपलब्ध था, तो यह कोड:

bool ok = true; //becomes false when at least a function returns false
ok &&= f1();
ok &&= f2(); //we may expect f2() is called whatever the f1() returned value

के बराबर है:

bool ok = true;
if (ok) ok = f1();
if (ok) ok = f2(); //f2() is called only when f1() returns true

यह पहला कोड त्रुटि-प्रवण है क्योंकि कई डेवलपर्स को लगता f2()है कि हमेशा जो भी f1()लौटाया गया है उसे मूल्य कहा जाएगा । यह लिखने की तरह है bool ok = f1() && f2();जहां रिटर्न मिलने पर f2()ही कॉल किया जाता f1()है true

  • यदि डेवलपर वास्तव में f2()केवल f1()रिटर्न देने के लिए बुलाया जाना चाहता है true, इसलिए ऊपर दूसरा कोड कम त्रुटि वाला है।
  • Else (डेवलपर f2()हमेशा कहा जाना चाहता है), &=पर्याप्त है:

के लिए उदाहरण &=

bool ok = true;
ok &= f1();
ok &= f2(); //f2() always called whatever the f1() returned value

इसके अलावा, संकलक के लिए यह आसान है कि वह नीचे दिए गए कोड की तुलना में इस कोड को अनुकूलित करे:

bool ok = true;
if (!f1())  ok = false;
if (!f2())  ok = false;  //f2() always called

तुलना &&और&

हम सोच रहे होंगे कि क्या ऑपरेटरों &&और &जब पर लागू ही परिणाम देने के boolमूल्यों?

आइए निम्नलिखित C ++ कोड का उपयोग करके देखें:

#include <iostream>

void test (int testnumber, bool a, bool b)
{
   std::cout << testnumber <<") a="<< a <<" and b="<< b <<"\n"
                "a && b = "<< (a && b)  <<"\n"
                "a &  b = "<< (a &  b)  <<"\n"
                "======================"  "\n";
}

int main ()
{
    test (1, true,  true);
    test (2, true,  false);
    test (3, false, false);
    test (4, false, true);
}

आउटपुट:

1) a=1 and b=1
a && b = 1
a &  b = 1
======================
2) a=1 and b=0
a && b = 0
a &  b = 0
======================
3) a=0 and b=0
a && b = 0
a &  b = 0
======================
4) a=0 and b=1
a && b = 0
a &  b = 0
======================

निष्कर्ष

इसलिए हाँ हम बदल सकते हैं &&द्वारा &लिए boolमान ;-)
तो बेहतर उपयोग करने &=के बजाय &&=
हम &&=बूलियन के लिए बेकार के रूप में विचार कर सकते हैं ।

उसी के लिए ||=

ऑपरेटर |=की तुलना में त्रुटि-प्रवण भी कम है||=

यदि कोई डेवलपर चाहता f2()है कि केवल f1()रिटर्न दिया जाए false, इसके बजाय:

bool ok = false;
ok ||= f1();
ok ||= f2(); //f2() is called only when f1() returns false
ok ||= f3(); //f3() is called only when f1() or f2() return false
ok ||= f4(); //f4() is called only when ...

मैं निम्नलिखित और अधिक समझने योग्य विकल्प की सलाह देता हूं:

bool ok = false;
if (!ok) ok = f1();
if (!ok) ok = f2();
if (!ok) ok = f3();
if (!ok) ok = f4();
// no comment required here (code is enough understandable)

या यदि आप एक पंक्ति शैली में सभी पसंद करते हैं:

// this comment is required to explain to developers that 
// f2() is called only when f1() returns false, and so on...
bool ok = f1() || f2() || f3() || f4();

13
क्या होगा अगर मैं वास्तव में इस व्यवहार को चाहता हूं? यदि बाएं हाथ की अभिव्यक्ति गलत है, तो दाहिने हाथ की अभिव्यक्ति निष्पादित नहीं की जाती है। यह दो बार चर लिखने के लिए कष्टप्रद है, जैसेsuccess = success && DoImportantStuff()
निकल्स आर

1
मेरी सलाह है लिखना if(success) success = DoImportantStuff()। यदि कथन success &&= DoImportantStuff()की अनुमति दी गई थी, तो कई डेवलपर्स को लगता DoImportantStuff()है कि हमेशा जो भी मूल्य कहा जाता है success। आशा है कि यह उत्तर आपको आश्चर्यचकित करता है ... मैंने अपने उत्तर के कई हिस्सों में भी सुधार किया है। कृपया मुझे बताएं कि क्या मेरा जवाब अब अधिक समझ में आता है? (अपने टिप्पणी उद्देश्य के बारे में) चीयर्स, आप देखें
;; नितंब

9
"यदि बयान success &&= DoImportantStuff()की अनुमति दी गई थी, तो कई डेवलपर्स सोचेंगे DoImportantStuff()कि हमेशा सफलता का मूल्य कहा जाता है।" आप if (success && DoImportantStuff())हालांकि कह सकते हैं कि जब तक वे तर्क को याद करते हैं अगर सिंटैक्स के साथ उन्हें कोई परेशानी नहीं होनी चाहिए &&=
पायलट

2
मैं यह नहीं देखता कि लोग कैसे मान सकते हैं कि f1()हमेशा मूल्यांकन करता है, ok &&= f(1) लेकिन यह नहीं मानता कि यह हमेशा मूल्यांकन करता है ok = ok && f(1)। मेरे लिए बस संभावना के रूप में लगता है।
ईनपोकलूम

1
मैं वास्तव में चर v1 और अभिव्यक्ति e2 v1 += e2के v1 = v1 + e1लिए सिंटैक्टिक शुगर के बराबर होने की उम्मीद करता हूं । बस एक आशुलिपि अंकन, बस इतना ही।
einpoklum
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.