c++ - सी++-रिटर्न एक्स, वाई; मुद्दा क्या है?




syntax return-value (12)

मैं कुछ वर्षों से C और C ++ में प्रोग्रामिंग कर रहा हूं और अब मैं इसमें केवल एक कॉलेज का पाठ्यक्रम ले रहा हूं और हमारी पुस्तक में एक उदाहरण के लिए एक फ़ंक्शन था:

int foo(){
  int x=0;
  int y=20;
  return x,y; //y is always returned
}

मैंने ऐसा सिंटेक्स कभी नहीं देखा। वास्तव में, मैंने कभी भी पैरामीटर सूचियों के बाहर उपयोग किए गए ऑपरेटर को नहीं देखा है। यदि y को हमेशा लौटाया जाता है, तो बिंदु क्या है? क्या कोई ऐसा मामला है जहां रिटर्न स्टेटमेंट इस तरह बनाना होगा?

(इसके अलावा, मैंने C को भी टैग किया क्योंकि यह दोनों पर लागू होता है, हालांकि मेरी पुस्तक विशेष रूप से C ++ है)


यदि y को हमेशा लौटाया जाता है, तो बिंदु क्या है?

बिंदु x का साइड इफेक्ट है (यानी कॉमा ऑपरेटर के बाएं हाथ की तरफ)। विवरण के लिए उदाहरण देखें जस्टिन एथियर।

क्या कोई ऐसा मामला है जहां रिटर्न स्टेटमेंट इस तरह बनाना होगा?

एक उदाहरण C ++ 11 में C ++ 14 तक एक कॉन्स्ट्रेक्स फ़ंक्शन के लिए है: इस तरह के फ़ंक्शन में मनमाने ढंग से बयान नहीं हो सकते हैं, लेकिन वास्तव में कोई रिटर्न स्टेटमेंट नहीं है।

यहाँ CppCon 2016 में पैट्रीस रॉयस "द एक्सेप्शन सिचुएशन" से एक कोड नमूना है:

constexpr int integral_div(int num, int denom) {
    return assert(denom != 0), num / denom;
}

अल्पविराम ऑपरेटर मुख्य रूप से इस तरह for बयानों के for उपयोग किया जाता है:

for( int i=0, j=10; i<10; i++, j++ )
{
    a[i] = b[j];
}

पहला अल्पविराम अल्पविराम ऑपरेटर नहीं है, यह घोषणा सिंटैक्स का हिस्सा है। दूसरा अल्पविराम ऑपरेटर है।


इस वाक्यविन्यास का उपयोग if - स्टेटमेंट के अतिरिक्त स्कोप ब्रैकेट्स को बचाने के लिए किया जा सकता है। उदाहरण के लिए आम तौर पर आप निम्नलिखित लिखेंगे:

if (someThing == true)
{
    a = 1;
    b = 2;
    return true;
}

इसे निम्नलिखित द्वारा प्रतिस्थापित किया जा सकता है:

if (someThing == true)
    return a = 1, b = 2, true;

मुझे लगता है कि इस कोडिंग शैली का उपयोग स्वच्छ कोड लिखने के बजाय आग्रह करने के लिए प्रेरित है।


उस रिटर्न स्टेटमेंट का कोई मतलब नहीं है।

यदि x को volatile घोषित किया जाता है, तो यह एक पहुंच को मजबूर करेगा (चूंकि कम से कम C ++ में volatile चर को बाहरी व्यवहार माना जाता है), लेकिन ऐसा नहीं है।

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

इसलिए, return x, y; स्टेटमेंट return y; जैसी ही बात है return y; । यदि x को निष्पादित करने के लिए सिर्फ एक पूरी तरह से व्यर्थ बात नहीं थी, तो इसे x; return y; रूप में लिखने के लिए स्टाइलिस्टिक रूप से बेहतर होगा x; return y; x; return y; , जो सटीक एक ही बात है। यह लगभग उस तरह से भ्रमित नहीं होगा।


क्या कोई ऐसा मामला है जहां रिटर्न स्टेटमेंट इस तरह बनाना होगा?

IMO, मैं पुस्तक के उदाहरण जैसे फ़ंक्शन में कई रिटर्न का उपयोग कभी नहीं करूंगा। यह संरचित डिजाइन का उल्लंघन करता है। फिर भी, कई प्रोग्रामर हैं जो करते हैं! किसी और के कोड को डीबग करना मैंने प्रत्येक रिटर्न स्टेटमेंट में एक वैश्विक वैरिएबल को एक मान दिया है, ताकि मैं यह पता लगा सकूं कि किस रिटर्न पर अमल हुआ।


जब return कीवर्ड के साथ उपयोग किया जाता है, तो अल्पविराम ऑपरेटर अंतिम मूल्य देता है, जो शुरू में भ्रमित होता है, लेकिन चीजों को अधिक संक्षिप्त बना सकता है।

उदाहरण के लिए, निम्न प्रोग्राम 2 की स्थिति कोड के साथ बाहर निकल जाएगा।

#include <iostream>
using namespace std;

void a() {
    cout << "a" << endl;
}


int one() {
    cout << "one" << endl;
    return 1;
}

int zero() {
    cout << "zero" << endl;
    return 0;
}

int main() {
    return one(), a(), zero(), 2;
}

निम्नलिखित के साथ संकलन और निष्पादित करते समय, आप नीचे आउटपुट देखेंगे।

michael$ g++ main.cpp -o main.out && ./main.out ; echo $?
one
a
zero
2

पैरामीटर सूचियों में अल्पविराम बस मापदंडों को अलग करने के लिए है, और अल्पविराम ऑपरेटर के समान नहीं है। अल्पविराम ऑपरेटर, आपके उदाहरण में, x और y दोनों का मूल्यांकन करता है, और फिर x को दूर फेंकता है।

इस मामले में, मुझे लगता है कि यह किसी ऐसे व्यक्ति द्वारा गलती है जो दो मूल्यों को वापस करने की कोशिश करता है, और यह नहीं जानता कि यह कैसे करना है।


मैंने इस सिंटैक्स का उपयोग सी में उपयोग किया है जब एक ऑपरेशन में मिडवे को वापस करते समय हाउसकीपिंग करते हैं। निश्चित रूप से बनाए रखने योग्य कोड नहीं:

int foo(int y){
  char *x;
  x = (char*)malloc(y+1);
  /** operations */
  if (y>100) return free(x),y;
  /** operations */
  if (y>1000) return free(x),y;

}

यह अल्पविराम ऑपरेटर है। ऐसे सिंटैक्स का उपयोग अप्रयुक्त चर x बारे में संकलक से चेतावनी को निष्क्रिय करने के लिए किया जा सकता है।


यह कोड के एक भयानक उदाहरण की तरह दिखता है। यह C / C ++ में मान्य सिंटैक्स हो सकता है, लेकिन मैं एक कारण नहीं सोच सकता कि आप ऐसा क्यों करना चाहते हैं।

यदि आप x और y दोनों वापस करना चाहते हैं, तो C ++ में इसे करने का एक बेहतर तरीका एक "पॉइंट" वर्ग या संरचना को x और y गुणों के साथ परिभाषित करना होगा, और उसे वापस करना होगा। एक अन्य विकल्प संदर्भ द्वारा x और y में पास करना होगा, फिर विधि में उचित रूप से मान सेट करें।

यदि विधि अभी y वापस करने जा रही है, तो मैं सिर्फ "वापसी y" होगा। यदि x को रिटर्न स्टेटमेंट से पहले "मूल्यांकन" करना है, तो इसे एक अलग लाइन पर किया जाना चाहिए।


यहां टिप्पणी करने वाले सभी लोग सोचते हैं कि यह व्यर्थ है और मैं असहमत नहीं हूं, बस उदाहरण देख रहा हूं, मैं यह अनुमान लगाने जा रहा हूं कि यह ज्यादा बेहतर नहीं है:

लेखक को फ़ंक्शन के भीतर उपयोग नहीं किए जाने के बारे में एक संकलक चेतावनी मिल रही थी, और चेतावनी को दूर करने के लिए यह एक आसान तरीका था।


सी के अनुसार

संक्षेप में कहा गया है, सामान्य अभिव्यक्ति में अल्पविराम ऑपरेटर का अर्थ है

e1, e2

"सबप्रेशन ई 1 का मूल्यांकन करें, फिर ई 2 का मूल्यांकन करें; अभिव्यक्ति का मूल्य ई 2 का मूल्य है।" इसलिए, e1 में एक असाइनमेंट या एक इंक्रीमेंट ++ या डिक्रीमेंट - या फ़ंक्शन कॉल या कुछ अन्य प्रकार के साइड इफेक्ट शामिल थे, क्योंकि अन्यथा यह एक मूल्य की गणना करेगा जिसे त्याग दिया जाएगा।

इसलिए मैं आपसे सहमत हूं, यह स्पष्ट करने के अलावा और कोई मतलब नहीं है कि यह वैध वाक्यविन्यास है, यदि है।

यदि आप C या C ++ में दोनों मानों को वापस करना चाहते हैं, तो आप एक x और y सदस्यों वाली struct बना सकते हैं, और इसके बजाय संरचना वापस कर सकते हैं:

struct point {int x; int y;};

आप तब एक प्रकार और सहायक फ़ंक्शन को परिभाषित कर सकते हैं जिससे आप आसानी से struct भीतर दोनों मानों को वापस कर सकते हैं:

typedef struct point Point;

Point point(int xx, int yy){
  Point p;
  p.x = xx;
  p.y = yy;
  return p;
}

और फिर सहायक फ़ंक्शन का उपयोग करने के लिए अपना मूल कोड बदलें:

Point foo(){
  int x=0;
  int y=20;
  return point(x,y); // x and y are both returned
}

और अंत में, आप इसे आज़मा सकते हैं:

Point p = foo();
printf("%d, %d\n", p.x, p.y);

यह उदाहरण C और C ++ दोनों में संकलित है। यद्यपि, जैसा कि मार्क नीचे सुझाव देता है, सी ++ में आप point संरचना के लिए एक कंस्ट्रक्टर को परिभाषित कर सकते हैं जो अधिक सुरुचिपूर्ण समाधान का समर्थन करता है।

एक ओर ध्यान दें, सीधे कई मूल्यों को वापस करने की क्षमता अद्भुत है जैसे पायथन जैसी भाषाएं जो इसका समर्थन करती हैं:

def foo():
  x = 0
  y = 20
  return x,y # Returns a tuple containing both x and y

>>> foo()
(0, 20)




comma-operator