स्ट्रिंग क्यों करता है :: एक इंट रिटर्न की तुलना करें?


102

छोटे प्रकार के बजाय या जैसे क्यों string::compareलौटता है ? मेरी समझ यह है कि यह विधि केवल -1, 0 या 1 रिटर्न करती है।intshortchar

दूसरा हिस्सा है, अगर मैं एक तुलना विधि उस प्रकार के दो वस्तुओं तुलना डिजाइन करने के लिए था Fooऔर मैं केवल वापस जाने के लिए -1 चाहता था, 0 या 1, का उपयोग करते हुए हैं shortया charआम तौर पर हो सकता है एक अच्छा विचार है?

संपादित करें: मुझे ठीक कर दिया गया है, string::compare-1, 0, या 1 नहीं लौटाता, यह वास्तव में एक मान> 0, <0 या 0. लौटाता है, मुझे लाइन में रखने के लिए धन्यवाद।

ऐसा लगता है कि इसका उत्तर मोटे तौर पर है, एक प्रकार का छोटे से लौटने का कोई कारण नहीं है intक्योंकि रिटर्न मान "rvalues" हैं और उन "rvalues" का प्रकार int (4 बाइट्स) से छोटा होने से कोई लाभ नहीं है। साथ ही, कई लोगों ने बताया कि अधिकांश प्रणालियों के रजिस्टरों का आकार संभवतः intवैसे भी होता है, क्योंकि ये रजिस्टर भरे जाने वाले हैं, चाहे आप उन्हें 1, 2 या 4 बाइट मूल्य दें, उन्हें वापस करने का कोई वास्तविक लाभ नहीं है छोटा मूल्य।

EDIT 2: वास्तव में ऐसा लगता है कि छोटे डेटाटाइप्स जैसे कि संरेखण, मास्किंग आदि का उपयोग करते समय अतिरिक्त प्रसंस्करण ओवरहेड हो सकता है। आम सहमति यह है कि बहुत सारे डेटा के साथ काम करते समय छोटे डेटाटाइप्स मेमोरी पर संरक्षण के लिए मौजूद होते हैं, जैसे कि एक सरणी का मामला।

आज कुछ सीखा, फिर से धन्यवाद दोस्तों!


मुझे लगता है कि क्या बेहतर होगा यदि कोई अधिक विशिष्ट प्रकार होता है जो इसके लिए इस्तेमाल किया जा सकता है। एक जिसमें Ada95 की शैली में केवल -1, 0 और 1 होता है।
सचिन कांठ

23
आपके लिए दस्तावेज़ string::compare()स्पष्ट रूप से रिटर्न वैल्यू से लिंक करता है <0, 0, और> 0 -not- -1, 0 और 1.
कैप्टेन ओब्लासियस

6
के बजाय shortया का उपयोग charकरने का क्या फायदा होगा int? अधिकांश आर्किटेक्चर एक फ़ंक्शन के रिटर्न मान को एक रजिस्टर में संग्रहीत करने जा रहे हैं, और intएक रजिस्टर में भी फिट होंगे shortया साथ ही char। और charसंख्यात्मक प्रकारों के लिए उपयोग करना हमेशा एक बुरा विचार है, खासकर जब आपको हस्ताक्षरित मूल्यों की गारंटी देने की आवश्यकता होती है, तो उन्हें सही तरीके से नियंत्रित किया जाता है।
कोड़ी ग्रे

7
कप्तान विवादास्पद, आपका नाम और टिप्पणी ... बस अनमोल।
कोडी स्मिथ

2
उपयोग charकरना एक बुरा विचार होगा, क्योंकि यदि यह शून्य से कम है तो रिटर्न वैल्यू के लिए कोड की जाँच उन प्लेटफार्मों पर विफल हो जाएगी, जहाँ पर charयह अहस्ताक्षरित है।
सहस्राब्दी

जवाबों:


113

सबसे पहले, विनिर्देश यह है कि यह मान से कम या अधिक से अधिक या उससे अधिक के बराबर मूल्य लौटाएगा 0, जरूरी नहीं -1या 1। दूसरे, रिटर्न वैल्यू रूवल हैं, इंटीग्रल प्रमोशन के अधीन हैं, इसलिए कुछ भी छोटा करने का कोई मतलब नहीं है।

C ++ में (C के रूप में), प्रत्येक अभिव्यक्ति या तो एक लकीर या एक लवल्यू है। ऐतिहासिक रूप से, शब्द इस तथ्य को संदर्भित करते हैं कि एक असाइनमेंट के बाईं ओर अंतराल दिखाई देते हैं, जहां प्रतिद्वंद्विता केवल दाईं ओर दिखाई दे सकती है। आज, गैर-श्रेणी के प्रकारों के लिए एक सरल अनुमान यह है कि स्मृति में एक लवल्यू का एक पता होता है, जो एक लकीर नहीं है। इस प्रकार, आप एक प्रतिद्वंद्विता का पता नहीं लगा सकते हैं, और सीवी-क्वालिफायर (जो कि "पहुंच") लागू नहीं होते हैं। C ++ शब्दों में, एक प्रकार का वर्ग जिसके पास वर्ग प्रकार नहीं है, एक शुद्ध मूल्य है, वस्तु नहीं। किसी फ़ंक्शन का रिटर्न मान तब तक एक प्रतिद्वंद्विता है, जब तक कि उसके पास संदर्भ प्रकार न हो। (गैर-श्रेणी के प्रकार जो एक रजिस्टर में फिट होते हैं, लगभग हमेशा एक रजिस्टर में वापस आ जाएंगे, उदाहरण के लिए, बजाय स्मृति में।)

वर्ग प्रकारों के लिए, मुद्दे कुछ अधिक जटिल हैं, इस तथ्य के कारण कि आप सदस्य कार्यों को एक बार में कॉल कर सकते हैं । इसका मतलब यह है कि प्रतिद्वंद्वियों के पास this सूचक के लिए वास्तव में पते होने चाहिए , और सीवी-योग्य हो सकते हैं, क्योंकि सीवी-योग्यता अधिभार संकल्प में भूमिका निभाती है। अंत में, C ++ 11 कई नए भेदों का परिचय देता है, ताकि क्रम में संदर्भों का समर्थन किया जा सके; ये भी, मुख्य रूप से वर्ग प्रकारों के लिए लागू होते हैं।

इंटीग्रल प्रमोशन से तात्पर्य इस तथ्य से है कि जब अभिन्न प्रकार से छोटे अभिन्न प्रकार intको अभिव्यक्ति के रूप में उपयोग किया जाता है, तो अधिकांश संदर्भों में, उन्हें पदोन्नत किया जाएगा int। तो एक चर घोषित भले ही मैं है short a, b;, अभिव्यक्ति में a + b, दोनों aऔर bकरने के लिए प्रोत्साहित कर रहे हैं intइससे पहले कि इसके अलावा होता है। इसी तरह, अगर मैं लिखने a < 0, तुलना के मूल्य पर किया जाता है a, एक करने के लिए परिवर्तित int। व्यवहार में, ऐसे बहुत कम मामले होते हैं, जहाँ इससे फर्क पड़ता है, कम से कम 2 कंपल्स मशीनों पर जहां पूर्णांक अंकगणित लपेटता है (यानी सभी लेकिन बहुत कुछ एक्सोटिक, आज-मुझे लगता है कि यूनिसिस मेनफ्रेम केवल एकमात्र अपवाद हैं)। फिर भी, अधिक सामान्य मशीनों पर भी:

short a = 1;
std::cout << sizeof( a ) << std::endl;
std::cout << sizeof( a + 0 ) << std::endl;

अलग-अलग परिणाम देना चाहिए: पहला इसके समकक्ष है sizeof( short ), दूसरा sizeof( int )(अभिन्न पदोन्नति के कारण)।

ये दो मुद्दे औपचारिक रूप से रूढ़िवादी हैं; प्रतिद्वंद्विता और अंतराल का अभिन्न संवर्धन से कोई लेना-देना नहीं है। सिवाय ... अभिन्न पदोन्नति केवल प्रतिद्वंद्वियों पर लागू होती है, और अधिकांश (लेकिन सभी नहीं) उन मामलों में जहां आप एक प्रतिद्वंद्विता का उपयोग करेंगे अभिन्न पदोन्नति में परिणाम होगा। इस कारण से, वास्तव में छोटे से कुछ में संख्यात्मक मान वापस करने का कोई कारण नहीं है int। चरित्र प्रकार के रूप में इसे वापस नहीं करने का एक बहुत अच्छा कारण है। ओवरलोडेड ऑपरेटर, जैसे <<, अक्सर चरित्र प्रकारों के लिए अलग व्यवहार करते हैं, इसलिए आप केवल चरित्र प्रकारों के रूप में पात्रों को वापस करना चाहते हैं। (आप अंतर की तुलना कर सकते हैं:

char f() { return 'a'; }
std::cout << f() << std::endl;      //  displays "a"
std::cout << f() + 0 << std::endl;  //  displays "97" on my machine

अंतर यह है कि दूसरे मामले में, इसके अलावा अभिन्न पदोन्नति हुई है, जिसके परिणामस्वरूप एक अलग अधिभार <<चुना जाना है।


46
यह अच्छा होगा यदि आप return values are rvalues, subject to integral promotionअपने उत्तर में अधिक व्याख्या कर सकते हैं ।
एल्विन वोंग

"रिटर्न वैल्यू रूवल हैं ... इसलिए कुछ भी छोटा करने का कोई मतलब नहीं है" LIKE IT
masoud

1
@ एल्विनगॉन्ग: उत्तर देखें कि वर्णों के बजाय C वर्ण शाब्दिक क्यों हैं? कुछ और पृष्ठभूमि की जानकारी के लिए।
जेसी गुड

मेरी इच्छा है कि मैं इसे फिर से +1 कर सकूं, शानदार विवरण के बाद आपका संपादन जोड़ा गया।
कोड़ी ग्रे

अगर होता तो क्या होता signed char? क्या यह एक हस्ताक्षरित के समान व्यवहार charकरेगा, या यह एक अलग प्रकार होगा?
user541686

41

यह जानबूझकर है कि यह -1, 0 या 1 नहीं लौटाता है।

यह अनुमति देता है (ध्यान दें कि यह तार के लिए नहीं है, लेकिन यह तार के लिए समान रूप से लागू होता है)

int compare(int *a, int *b)
{
   return *a - *b;
}

जो बहुत कम बोझिल है:

int compare(int *a, int *b)
{
   if (*a == *b) return 0;
   if (*a > *b) return 1;
   return -1;
}

यदि आपको ऐसा करना है तो [या उन पंक्तियों के साथ कुछ]] यदि आपको -1, 0 या 1 वापस करना है।

और यह अधिक जटिल प्रकारों के लिए भी काम करता है:

class Date
{
    int year;
    int month;
    int day;
}

int compare(const Date &a, const Date &b)
{
   if (a.year != b.year) return a.year - b.year;
   if (a.month != b.month) return a.month - b.month;
   return a.day - b.day;
}

स्ट्रिंग मामले में, हम यह कर सकते हैं:

int compare(const std::string& a, const std::string& b)
{
   int len = min(a.length(), b.length());

   for(int i = 0; i < len; i++)
   {
      if (a[i] != b[i]) return a[i] - b[i];
   }
   // We only get here if the string is equal all the way to one of them
   // ends. If the length isn't equal, "longest" wins. 
   return a.length() - b.length();
}

8
आपके पहले compareफ़ंक्शन में अतिप्रवाह के साथ समस्याएं हैं जो (सौभाग्य से) समान रूप से लागू नहीं होती हैं यदि यह लेता है char*और इससे charछोटा है int। उदाहरण के लिए, यदि *aहै MAX_INTऔर *bहै -1तो *a - *bयूबी है, लेकिन अगर कार्यान्वयन द्वारा अपने व्यवहार तो परिणाम लगभग निश्चित रूप से परिभाषित करने के लिए नकारात्मक है।
स्टीव जेसप

1
अपने अंतिम उदाहरण के साथ समस्या: length()एक रिटर्न size_t, जो की तुलना में बड़ा हो सकता है int...
F'x

यदि आपके तार 2GB से अधिक लंबे हैं तो हाँ, यह एक समस्या हो सकती है। मैंने एक बार पंद्रो में चीजों को संग्रहीत करने के लिए परीक्षण-मामले के रूप में 1 जीबी लंबे स्ट्रिंग्स किए हैं। लेकिन यकीन है, एक MPEG के साथ एक स्ट्रिंग से निपटने वाले किसी व्यक्ति ने Base64 के रूप में एन्कोड किया या कुछ इस तरह से उस समस्या में भाग सकता है ...
मैट पीटरसन

@MatsPetersson यह एक मूलभूत समस्या है, क्योंकि सवाल यह है कि "यह एक इंट क्यों लौटाता है?"
F'x

ठीक है, मुझे यकीन है कि यह हिस्टेरिकल है - मेरा मतलब ऐतिहासिक कारण है - और शायद इसलिए कि यह स्ट्रैम्प / मेम्कम्प और अन्य प्रकार के ऑपरेशनों के साथ संगत है।
मैट पीटरसन

25

int आमतौर पर (अधिकांश आधुनिक हार्डवेयर पर अर्थ होता है) सिस्टम बस और / या सीपीयू रजिस्टरों के समान आकार का एक पूर्णांक, जिसे मशीन शब्द कहा जाता है। इसलिए int को आमतौर पर छोटे प्रकारों की तुलना में तेजी से पास किया जाता है, क्योंकि इसमें संरेखण, मास्किंग और अन्य संचालन की आवश्यकता नहीं होती है।

छोटे प्रकार मुख्य रूप से सरणियों और संरचनाओं के लिए रैम उपयोग अनुकूलन की अनुमति देने के लिए मौजूद हैं। ज्यादातर मामलों में वे बेहतर रैम उपयोग के लिए कुछ सीपीयू साइकिल (एलिगेंट ऑपरेशन के रूप में) का व्यापार करते हैं।

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


एक तरह से चीजों के हार्डवेयर-साइड को समझाने का शानदार तरीका।
ओगरे Psalm33

10

यह एक सी-आइएसएम है।

जब C compare-type फ़ंक्शन की आवश्यकता होती है, तो वे हमेशा एक लौटते हैं int। C ++ ने बस उसे आगे बढ़ाया (दुर्भाग्य से)।

हालांकि, intवास्तविक रूप से लौटना संभवत: सबसे तेज़ तरीका है, क्योंकि यह आमतौर पर उपयोग में सिस्टम के रजिस्टरों का आकार है। (जानबूझकर अस्पष्ट।)


1
असल में shortऔर charप्रदर्शन दंड, जैसे लागू कर सकते हैं 255+7एक के लिए एक अलग महत्व है charऔर एक intतो एक सही कार्यान्वयन जरूरी नहीं कि सिर्फ एक स्टोर कर सकते हैं char, जहां एक intइसके सिमेंटिक सौंपने की देखभाल के बिना जा सकते हैं। कंपाइलर अनिवार्य रूप से इस अक्षमता को अक्षम नहीं करेगा।
बजे जैक आइडली

10

विधि वास्तव में सेट में एक पूर्णांक नहीं लौटाती है { -1, 0, 1 }; यह वास्तव में कोई अभिन्न मूल्य हो सकता है ।

क्यों? मुख्य कारण जो मैं सोच सकता हूं, वह यह intहै कि वास्तुकला के लिए "प्राकृतिक आकार" मूल्य माना जाता है; इस आकार के मानों का संचालन आमतौर पर छोटे या बड़े मूल्यों के संचालन की तुलना में कम से कम (और कई मामलों में तेज) होता है। तो यह कार्यान्वयन का एक मामला है जो सबसे तेज़ होने के लिए पर्याप्त सुस्त उपयोग की अनुमति देता है।


4

अगर मैं एक तुलना विधि डिजाइन करने के लिए था, जो कि फू की दो वस्तुओं की तुलना करता है और मैं केवल -1, 0 या 1 वापस करना चाहता था, तो क्या संक्षिप्त या चार का उपयोग करना आम तौर पर एक अच्छा विचार होगा?

यह ठीक होगा। एक बेहतर तरीका यह होगा कि आप एक बूल वापस करें (यदि केवल तुलना करना चाहते हैं तो), या एनम (अधिक जानकारी के लिए):

enum class MyResult
{
  EQUAL,
  LESS,
  GREATER
};

MyResult AreEqual( const Foo &foo1, const Foo & foo2 )
{
  // calculate and return result
}

3
"यह ठीक रहेगा।" क्या आपके पास इसके लिए एक औचित्य है?
ज्रोक

4

मान लीजिए कि कुछ लोग C से C ++ तक का कोड बदल रहे हैं। उन्होंने बदलने strcmpका फैसला किया string::compare

strcmpरिटर्न के बाद से int, उपहार के रूप में string::compareलौटना आसान है int


2

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

इसके अलावा, रिटर्न वैल्यू सिर्फ -1, 0या 1लेकिन <0, 0या नहीं है >0

इसके अलावा, जैसा कि उल्लेख किया गया था कि वापसी अभिन्न पदोन्नति के अधीन है, इसे छोटा बनाने का कोई मतलब नहीं है।


-1

क्योंकि एक बूलियन रिटर्न वैल्यू केवल दो संभावित मान (सत्य, असत्य) हो सकता है, और एक तुलना फ़ंक्शन तीन संभावित मान (कम, बराबर, अधिक से अधिक) वापस कर सकता है।

अपडेट करें

हालांकि निश्चित रूप से एक हस्ताक्षरित शॉर्ट को वापस करना संभव है, अगर आप वास्तव में अपने स्वयं के तुलना फ़ंक्शन को लागू करना चाहते थे , तो आप दो बूलियनों के साथ एक कुतरना या संरचनात्मक मान वापस कर सकते थे।


7
प्रश्न में कहीं भी यह बूलियन प्रकार को वापस करने के बारे में कुछ नहीं कहता है। वास्तव में, वह विशेष रूप से प्रस्तावित करता है shortऔर charविकल्प के रूप में int
कोड़ी ग्रे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.