सहायक ऑपरेटर ?: बनाम अगर ... और नहीं


80

C ++ में, है ?: ऑपरेटर तेजी से अगर () ... और कथनों? संकलित कोड में उनके बीच कोई अंतर हैं?


मुश्किल सवाल, क्योंकि यह कंपाइलर के इष्टतमकरण सेटिंग पर भी निर्भर करेगा।
extraneon

3
यह निश्चित रूप से इस बात पर निर्भर करता है कि आप शाखाओं के अंदर क्या करते हैं। सशर्त ऑपरेटर केवल अभिव्यक्ति की ifअनुमति देता है जबकि बयान की अनुमति देता है।
गुमबू


8
कुछ लोग बेतरतीब ढंग से मेरे पूरी तरह से ठीक तीन साल पुराने सवाल को संपादित करने का फैसला किया, सवाल फिर से लिखना तो यह मेरे विपरीत पूरी तरह से लगता है और कुछ पूरी तरह से अनावश्यक कोड जोड़ रहा है जो पूरी समस्या को व्यर्थ कर देता है, क्योंकि निरंतर तह के लिए धन्यवाद, दोनों नमूने सरल "परिणाम को कम करते हैं" = 5 ”। वापस लाना।
Xirdus

असेंबली संस्करण cmov बनाम jmp stackoverflow.com/questions/14131096/…
Ciro Santilli 病 j j j ''

जवाबों:


88

आपके संकलक पर निर्भर करता है, लेकिन किसी भी आधुनिक संकलक पर आमतौर पर कोई अंतर नहीं होता है। यह कुछ ऐसा है जिसके बारे में आपको चिंता नहीं करनी चाहिए। अपने कोड की स्थिरता पर ध्यान केंद्रित करें।


1
+1 कई अनुप्रयोगों के लिए, वास्तव में डंप संकलक पर भी पूर्ण अंतर पर विचार करने लायक नहीं है।

4
कोड की स्थिरता के बारे में मैं पसंद करूंगा अगर ... और। कम से कम मेरे लिए इसे पढ़ना आसान है।
Exa

2
@Exa: संदर्भ पर निर्भर करता है। जब आप किसी ऑब्जेक्ट को इनिशियलाइज़ कर रहे होते हैं तो टर्नेरी ऑपरेटर अक्सर बेहतर होता है।
निमंजा ट्रिफ़ुनोविक

@ नेमजा: इसीलिए मैंने कहा "कम से कम मेरे लिए"। मैं कोड की पठनीयता की बात कर रहा था :)
Exa

1
@kotlinski, मैं नहीं कह रहा हूँ एक सशर्त एक से कम बनाए रखने योग्य है। वे दोनों स्पष्ट, भिन्न, परिस्थितियों में स्पष्ट हैं, जैसा कि टर्नरी के उत्तर में वर्णित है या ऊपर वर्णित त्रिकोणीय के लिए नहीं है
पोटोमैटो

106

यह तेज नहीं है। जब आप कुछ अभिव्यक्ति के आधार पर एक स्थिर चर को इनिशियलाइज़ कर सकते हैं तो एक अंतर होता है:

const int x = (a<b) ? b : a;

आप ऐसा नहीं कर सकते if-else


20
@ डायवर्टर कला: जो एक constचर के साथ संभव नहीं है ।
जॉब

1
आप एक नॉन-कास्ट वैरिएबल बना सकते हैं, यदि उसमें / और में असाइन करते हैं, तो एक नया कास्ट वैरिएबल बनाएं और इसे नॉन-कास्ट के साथ बनाएँ। बल्कि बेकार, लेकिन असंभव से बहुत दूर।
पिल्ला

7
अच्छे ओल के बारे में क्या ’ max? const int x = max(a,b);ठीक काम करता है।
बॉबोबो

3
@bobobobo हा! जब मैं आपकी टिप्पणी पढ़ता हूं तो मुझे लगता है कि आप जो सुझाव दे रहे थे वह था max ? const int x = max(a,b);और सोचा था कि वाह! ये क्या डब्ल्यूटीएफ है! तो मैं इसे फिर से पढ़ा और देखा कि प्रश्न चिह्न मोनोस्पेस नहीं था! विषय दिया, मुझे लगता है कि मैं सोच में उचित था? कमान का हिस्सा था! :)
डेढ़

2
आप उपयोग कर सकते हैं const int x = [&] -> int { if (a < b) return b; else return a; }
एलएफ

43

मैंने GCC को सशर्त ऑपरेटर को cmov(सशर्त चाल) निर्देशों में बदलते हुए देखा है, जबकि ifशाखाओं में बयान देते हुए , जो हमारे मामले में मतलब था, सशर्त ऑपरेटर का उपयोग करते समय कोड तेज था। लेकिन यह कुछ साल पहले था, और आज की संभावना है, दोनों एक ही कोड के लिए संकलन करेंगे।

वहाँ कोई गारंटी नहीं है कि वे एक ही कोड के लिए संकलन करेंगे। यदि आपको प्रदर्शन की आवश्यकता है, तो हमेशा की तरह मापें । और जब आपने मापा और पता चला कि 1. आपका कोड बहुत धीमा है, और 2. यह कोड का यह विशेष हिस्सा है जो अपराधी है, तो कंपाइलर द्वारा उत्पन्न असेंबली कोड का अध्ययन करें और अपने लिए जांचें कि क्या हो रहा है।

अगर मैं सशर्त ऑपरेटर का उपयोग करता हूं, तो "संकलक हमेशा अधिक कुशल कोड उत्पन्न करेगा" जैसे सुनहरे नियमों पर भरोसा न करें।


2
+1। जब मैं GCC का उपयोग करते हुए PS3 के लिए विकसित कर रहा था, तो शाखाओं से बचने के लिए "यदि" के बजाय सशर्त का उपयोग करना उपयोगी था।
जोहान कोटलिंस्की

क्या यह सी भाषा के लिए विशिष्ट है? C ++ का मानक कहता है कि Only one of the second and third expressions is evaluated. Every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second or third expression.कौन सा स्पष्ट रूप से संकलक को एक cmoveनिर्देश उत्पन्न करने से रोकता है ।
Joey.Z

2
@zoujyjs नहीं, C का एक ही नियम है। लेकिन जैसे-अगर नियम के तहत, कंपाइलर धोखा देने के लिए स्वतंत्र है, जब तक कि अंतिम परिणाम सही हो। तो जब तक कोई साइड इफेक्ट नहीं होते हैं, तब तक कंपाइलर यह अनुकूलन कर सकता है।
jalf

सेमीोव के साथ और कैसे लागू किया जाए? एक मूव टू वेल्यू 1 + एक सेमीोव टू वैल्यू 2?
सिरो सेंटिल्ली 郝海东 冠状 i i 法轮功

1
नोट: यह सलाह पुरानी है (cira 2010), मैं इसे gcc 4.4 या बाद में पुन: पेश नहीं कर सका।
चक्रीय

15

वे समान हैं, हालांकि, टर्नरी ऑपरेटर का उपयोग उन जगहों पर किया जा सकता है जहां पर अगर / का उपयोग करना मुश्किल है:

printf("Total: %d item%s", cnt, cnt != 1 ? "s" : "");

अगर / के साथ वह कथन करना, एक बहुत अलग संकलित कोड उत्पन्न करेगा।


8 साल बाद अपडेट ...

वास्तव में, मुझे लगता है कि यह बेहतर होगा:

printf(cnt == 1 ? "Total: %d item" : "Total: %d items", cnt);

(वास्तव में, मुझे पूरा यकीन है कि आप "% d" को "एक" के साथ पहली स्ट्रिंग में बदल सकते हैं)


8
एक टर्नरी ऑपरेटर की भी आवश्यकता नहीं है:printf("Total: %d item%s", cnt, "s" + (cnt==1));
MSalters

@MSalters लेकिन यह स्ट्रिंग के अंत में एक डबल नल देता है, जो अन्य स्थितियों में एक समस्या हो सकती है जहां डबल नल का अर्थ कुछ है (उदाहरण lpStrFilterके लिए OPENFILENAME संरचनाओं का सदस्य )
bobobobo

1
@bobobobo: नहीं, %sप्रिंट करता है, लेकिन \0स्रोत स्ट्रिंग से शामिल नहीं है ।
एमएसल्टर्स

@ मीडिया यह कैसे printf("Total: %d item%s", cnt, "s" + (cnt==1));काम करता है ?
क्विक

2
@ क्वर्क: (cnt==1)सच या गलत है, जो 0 या 1 में परिवर्तित होता है। "s" एक नेल-टर्मिनेटेड स्ट्रिंग का सूचक है। एक अक्षर को जोड़कर एक अक्षर (एस)। तो यह प्रिंट या तो "s" या "" है।
MSalters

3

बस थोड़ा सा बचे रहना है ...

x ? y : x = value

यदि x 0 नहीं है (तो) y को मान प्रदान करेगा ।


3
कोष्ठक के बिना नहीं: stackoverflow.com/questions/7499400/…
जैरी यिर्मयाह

1
गलत (देखें stackoverflow.com/a/7499505/2436175 )। इसके अलावा, यह सवाल के साथ क्या करना है?
एंटोनियो

3

संकलित कोड के बावजूद, वे शब्दार्थ रूप से भिन्न हैं। <cond>?<true expr>:<false expr>एक अभिव्यक्ति है और if..else..एक बयान है।

हालांकि सशर्त अभिव्यक्ति का वाक्यविन्यास अजीब लगता है, यह एक अच्छी बात है। आपको एक प्रदान करने के लिए मजबूर किया जाता है <false expr>और दो अभिव्यक्तियाँ टाइप की जाती हैं।

if..else..लिस्प, हास्केल जैसी अभिव्यक्ति-आधारित, कार्यात्मक भाषा के बराबर है? : के बजाय C ++ में, if..else..बयान।


2

आप इसे एक पंक्ति में रखने के लिए मजबूर नहीं हैं: -

x = y==1 ?
    2
    :// else
    3;

यह अगर / अन्यथा की तुलना में बहुत स्पष्ट है क्योंकि आप तुरंत देख सकते हैं कि दोनों शाखाओं को x को सौंपा जा रहा है।


तुम भी एक const
QuentinUK

0

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


0

सीए टर्नेरी ऑपरेटर में ?: "" फॉर्म के सशर्त अभिव्यक्ति के निर्माण के लिए उपलब्ध है

exp1 ? exp2:exp3

जहां exp1, exp2 और exp3 अभिव्यक्ति हैं

उदाहरण के लिए

        a=20;
        b=25;
        x=(a>b)?a:b;

        in the above example x value will be assigned to b;

यह if..else स्टेटमेंट निम्नानुसार उपयोग करके लिखा जा सकता है

            if (a>b)
             x=a;
             else
             x=b;

** इसलिए इन दोनों में कोई अंतर नहीं है। यह प्रोग्रामर को आसानी से लिखने के लिए है, लेकिन कंपाइलर के लिए दोनों समान हैं। *


0

कुछ कोड उलटने के दौरान (जो मुझे याद नहीं है, कुछ साल पहले) मैंने मशीन कोड के बीच एकल लाइन अंतर देखा:? और अगर-और। Don't remember much but it is clear that implementation of both is different.

लेकिन मैं आपको सलाह देता हूं कि आप उनमें से किसी एक को अपनी दक्षता के अनुसार न चुनें, कोड की पठनीयता या अपनी सुविधा के अनुसार चुनें। हैप्पी कोडिंग


यह अंतर उनमें से एक था, जो ब्रांचिंग के लिए गोटो का उपयोग कर रहा था और अन्य सैम देशी निर्देश का उपयोग कर रहा था, मुझे याद नहीं है कि कौन सा उपयोग कर रहा था ..
परवेज आलम

0

टर्नेरी ऑपरेटर हमेशा एक मूल्य देता है। इसलिए ऐसी स्थिति में जब आप परिणाम से कुछ आउटपुट वैल्यू चाहते हैं और टर्नरी ऑपरेटर का उपयोग करने के लिए केवल 2 स्थितियां हमेशा बेहतर होती हैं। यदि उपर्युक्त शर्तों में से कोई भी सत्य नहीं है, तो अन्य का उपयोग करें।


6
वास्तव में यह क्या है? क्या आप जानते हैं कि आप किस बारे में बात कर रहे हैं?
क्वांटम

0

मुझे लगता है कि ऐसे हालात हैं जहां अगर इनलाइन काम करती है तो इनलाइन "तेज" कोड प्राप्त कर सकती है। वस्तु निर्माण और विनाश महंगा हो सकता है इसलिए निम्नलिखित परिदृश्य पर विचार करें:

class A{
    public:
    A() : value(0) {
        cout << "Default ctor" << endl;
    }
    A(int myInt) : value(myInt)
    {
        cout << "Overloaded ctor" << endl;
    }

    A& operator=(const A& other){
        cout << "= operator" << endl;
        value = other.value; 
    }

    ~A(){
        cout << "destroyed" << std::endl;
    }

    int value;

};


int main()
{
   {
       A a;
       if(true){
           a = A(5);
       }else{
           a = A(10);
       }
   }

   cout << "Next test" << endl;
   {
        A b = true? A(5) : A(10);
   }
   return 0;
}

इस कोड के साथ, आउटपुट होगा:

Default ctor                                                                                                                                                                                                                      
Overloaded ctor                                                                                                                                                                                                                   
= operator                                                                                                                                                                                                                        
destroyed                                                                                                                                                                                                                         
destroyed                                                                                                                                                                                                                         
Next test                                                                                                                                                                                                                         
Overloaded ctor                                                                                                                                                                                                                   
destroyed  

इसलिए, यदि हम, तो हम एक aही दायरे में जिंदा रखने के लिए आवश्यक ऑपरेशन का एक गुच्छा बचा लेते हैं b। हालांकि यह अत्यधिक संभावना है कि स्थिति मूल्यांकन की गति दोनों परिदृश्यों में बहुत समान है, बदलते गुंजाइश आपको अन्य कारकों को ध्यान में रखने के लिए मजबूर करते हैं कि इनलाइन अगर आपको बचने की अनुमति देती है।


और क्या हैA a(true ? 5 : 10);
क्वेस्ट

-1

अब मैं आपकी मदद नहीं कर सकता, मैं इसके नीचे एक द्वितीयक प्रश्न के साथ मदद करने में सक्षम हो सकता हूं, क्या मैं इसका उपयोग करना चाहता हूं? यदि आप केवल गति जानना चाहते हैं, तो बस मेरी टिप्पणी को अनदेखा करें।

सभी मैं कह सकता हूँ कि टर्नरी का उपयोग कब करना है? : ऑपरेटर। यह पठनीयता के लिए एक अभिशाप जितना आशीर्वाद हो सकता है।

अपने आप से पूछें कि क्या आपको इसे इस्तेमाल करने से पहले पढ़ना आसान लगता है

int x = x == 1 ? x = 1 : x = 1;

if (x == 1)
{
   x = 1
}
else
{
   x = 2
}

if (x == 1)
    x = 1
else
    x = 1

हां यह कोड को 100% फर्जी बनाने के लिए मूर्खतापूर्ण लगता है। लेकिन उस छोटी सी चाल ने मुझे कोड की अपनी पठनीयता का विश्लेषण करने में मदद की। यह उस नमूने में आपके द्वारा देखे जाने वाले ऑपरेटर की पठनीयता है, न कि सामग्री।

यह साफ-सुथरा रहता है, लेकिन औसत टॉयलेट सीट और डोरकनॉब

मेरे अनुभव में, जो सीमित है, मैंने देखा है कि बहुत कम लोग वास्तव में एक टर्नरी ऑपरेटर से आवश्यक जानकारी को जल्दी से प्रत्यर्पित करने में सक्षम होते हैं, जब तक कि यह 100% बेहतर न हो। जब मुझे लगता है कि यह खराब है, तो इसे ठीक करने के लिए एक दर्द है


5
पहली पंक्ति शायद पढ़नी चाहिए int x = x == 1 ? 1 : 2या संभवतःint x = (x == 1) ? 1 : 2
हस्त्कुरन

मेरी बात केवल कोड का दृश्य दिखाने के लिए थी, एक पंक्ति की साफ-सुथरी अच्छी है। लेकिन अगर आप CONDITION / ASSIGNEMENT देखना चाहते हैं तो कोड की सामग्री फर्जी हो सकती है। यदि आप स्पॉट करना चाहते हैं कि आप ऑपरेटर और अकेले स्थान को क्या देखते हैं। मुझे आईएफ और () शब्द पता है, आह, यह एक शर्त है। मुझे A = B दिखाई देता है? कथन: क्या आपने अपने लिए खुद को स्थान दिया है? अधिकांश लोग जो मुझे जानते हैं कि कार्यक्रम नहीं है, शायद यह इसलिए है क्योंकि अधिकांश लोग जानते हैं कि कार्यक्रम मेरी तरह बदमाश हैं। आप संख्या के सही होने के बारे में बकवास कर रहे हैं, यह बात है।
प्रोक्लीन अगे

2
पहली पंक्ति निश्चित रूप से कुछ कोष्ठकों की आवश्यकता है। शायद "int x = (y == 1)? 0: 1;" या "इंट x = ((y == 1)? 0: 1);"
सुपरकैट

6
मुझे क्षमा करें, लेकिन मुझे असाइनमेंट देखने में कोई समस्या नहीं है। यदि आप अपनी बात मनवाने के लिए उदाहरण का चयन करना चाहते हैं, तो यह आपकी समस्या है। आप x = x = 1;हर जगह क्यों नहीं लिखते हैं और फिर शिकायत करते हैं कि असाइनमेंट बहुत जटिल है और इसे टाला जाना चाहिए।
अंकलबीन्स

-4

नहीं, वे बिल्कुल एक ही निष्पादन योग्य कोड में परिवर्तित हो जाते हैं।


7
-1: किस संकलक के किस संस्करण पर, किस मंच पर, किस कोड के साथ?
पिल्ला

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