2012-01-03 7 views
83

इस में कांस्ट का उद्देश्य क्या है?कॉन्स वैल्यू द्वारा लौटने का उद्देश्य?

const Object myFunc(){ 
    return myObject; 
} 

मैं सिर्फ पढ़ने प्रभावी सी ++ और आइटम शुरू कर दिया है 3 अधिवक्ताओं इस और एक गूगल खोज समान सुझाव लेकिन यह भी जवाबी ऊपर उठाता है। मैं नहीं देख सकता कि यहाँ कांस्ट का उपयोग कैसे बेहतर होगा। मूल्य से वापसी मानना ​​वांछनीय है, मुझे लौटाए गए मूल्य की रक्षा करने का कोई कारण नहीं दिखता है। यह उदाहरण उपयोगी क्यों हो सकता है कि यह वापसी मूल्य के अनपेक्षित बूल कास्ट को रोक रहा है। वास्तविक समस्या यह है कि स्पष्ट बूल कास्ट स्पष्ट कीवर्ड से रोका जाना चाहिए।

यहां कांस्ट का उपयोग बिना असाइनमेंट के अस्थायी वस्तुओं का उपयोग रोकता है। तो मैं उन वस्तुओं के साथ अंकगणितीय अभिव्यक्ति नहीं कर सका। ऐसा लगता है कि ऐसा कोई मामला नहीं है कि एक अनाम नामक उपयोगी है।

यहां कॉन्स्ट का उपयोग करके प्राप्त किया जाता है और यह कब बेहतर होगा?

संपादित करें: किसी भी कार्य को अंकगणित उदाहरण बदलें जो किसी ऑब्जेक्ट को संशोधित करता है जिसे आप असाइनमेंट से पहले करना चाहते हैं।

+1

हां आप कॉन्स्ट ऑब्जेक्ट्स के साथ अंकगणित कर सकते हैं क्योंकि अंकगणित ऑपरेटरों को कॉन्स होना चाहिए और कॉन्स्ट ऑब्जेक्ट्स –

उत्तर

87

काल्पनिक स्थिति है जहाँ आप एक वस्तु पर एक संभावित महंगा गैर स्थिरांक आपरेशन प्रदर्शन कर सकता है में, स्थिरांक-मूल्य से लौटने अगर आप गलती से कॉल करने से रोकता है एक अस्थायी पर यह ऑपरेशन। कल्पना कीजिए कि + एक गैर स्थिरांक मान दिया है, और आप लिख सकते हैं:

(a + b).expensive(); 

की सी ++ 11 साल की उम्र में, हालांकि, यह दृढ़ता से गैर स्थिरांक के रूप में मान वापस जाने के लिए इतना है कि आप पूरा समय लग सकता है की सलाह दी है रावल संदर्भों का लाभ, जो केवल गैर-निरंतर राक्षसों पर समझ में आता है।

संक्षेप में, इस अभ्यास के लिए एक तर्क है, लेकिन यह अनिवार्य रूप से अप्रचलित है।

+0

खैर, हर्ब सटर [अनुशंसित लौटने वाले कॉन्स वैल्यू] (http://books.google.com/books?id = 58rZvOSuheEC और lpg = PA179 और ots = L_LgismXMo और dq = sutter% 20return% 20const% 20value और pg = PA179 # v = onepage और q और f = false) गैर-आदिम प्रकारों के लिए, लेकिन मुझे लगता है कि आप सही हैं कि सलाह अब अप्रचलित है। –

+10

@FredLarson: हाँ, 14 साल की एक पुस्तक में: -एस –

+0

यह उत्तर इंगित करता है कि कॉन्स्ट-वैल्यू द्वारा लौटने का अर्थ है const &&, लेकिन क्या यह वास्तव में सच है ?! जैसे वीएस 13 मुझे int && var = को एक फ़ंक्शन में बांधने की अनुमति देता है जो कॉन्स int देता है। "एक फ़ंक्शन को कॉल करने का नतीजा जिसका रिटर्न टाइप संदर्भ नहीं है"। –

32

It's prettypointless एक फ़ंक्शन से const मान वापस करने के लिए। क्या यह किसी भी है

struct T {}; 

const T foo() { 
    return T(); 
} 

int main() { 
    foo() = T(); 
} 

// error: passing ‘const T’ as ‘this’ argument of ‘T& T::operator=(const T&)’ discards qualifiers 

यह संदेहास्पद है:

const int foo() { 
    return 3; 
} 

int main() { 
    int x = foo(); // copies happily 
    x = 4; 
} 

and:

const int foo() { 
    return 3; 
} 

int main() { 
    foo() = 4; // not valid anyway for built-in types 
} 

// error: lvalue required as left operand of assignment 

हालांकि you can notice if the return type is a user-defined type

यह difficult यह आपके कोड पर कोई असर को पाने के लिए है किसी के लिए लाभ।

एक संदर्भ लौटने से अलग है, लेकिन जब तक Object कुछ टेम्पलेट पैरामीटर नहीं है, तो आप ऐसा नहीं कर रहे हैं।

+0

भी देखें नोट करें कि दूसरा उदाहरण केवल अंतर्निहित प्रकारों के लिए एक त्रुटि को ट्रिगर करता है। – Xeo

+0

क्या आप पहले उदाहरण पर विस्तार कर सकते हैं? यह मुझे यह कहने के लिए कोई समझ नहीं आता है कि वापसी मूल्य स्थिर होगा, लेकिन इसे गैर-कॉन्स्ट चर के लिए असाइन करने में सक्षम होना चाहिए। –

+1

@IvayloToskov: आपको जो भी विस्तार चाहिए, वह _in_ उदाहरण है, विशेष रूप से टिप्पणी जो "खुशी से प्रतियां" कहती है। 'Const int x = 4 पर विचार करें; int y = x; 'जो भी बिल्कुल ठीक है। –

-2

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

हालांकि किसी भी अनुकूलक सबसे अधिक संभावना यह वैसे भी बाहर का अनुकूलन होगा ...

+0

लेकिन वह 'ऑब्जेक्ट' वापस कर रहा है। –

+0

अनुकूलित करने के लिए कुछ भी नहीं है, कॉन्स्ट-नेस एक संकलन-समय सुरक्षा तंत्र है। –

+0

आह, मैंने इसे ऑब्जेक्ट * के रूप में गलत तरीके से पढ़ा है ... –

-3

myObject एक सूचक हो सकता है। 'कॉन्स्ट' वहाँ myObject द्वारा इंगित मूल्य की रक्षा कर रहा है।

+3

असल में, नहीं। ऑब्जेक्ट कॉन्स * 'ऑब्जेक्ट * कॉन्स' नहीं है। –

3

यह सुनिश्चित करता है कि लौटा ऑब्जेक्ट (जो उस बिंदु पर एक RValue है) को संशोधित नहीं किया जा सकता है। यह सुनिश्चित करें कि उपयोगकर्ता नहीं कर सकता इस तरह सोचता है कि बनाता है:

myFunc() = Object(...); 

अच्छी तरह से काम करेगा कि अगर myFunc संदर्भ द्वारा लौट आए, लेकिन लगभग निश्चित रूप से जब मूल्य द्वारा दिया एक बग है (और शायद द्वारा पकड़ा नहीं की जाएगी संकलक)। निश्चित रूप से सी ++ 11 में इसके राजस्व के साथ यह सम्मेलन उतना ही समझ में नहीं आता है जितना पहले किया गया था, क्योंकि एक कॉन्स ऑब्जेक्ट को स्थानांतरित नहीं किया जा सकता है, इसलिए इसका प्रदर्शन पर बहुत भारी प्रभाव हो सकता है।

+0

जो 'const' की व्याख्या नहीं करता है। –

+0

@ निकोल बोलास: यह कॉन्स्ट को कैसे समझाता नहीं है? संकलित करते समय कोड उदाहरण 'ऑब्जेक्ट' है, लेकिन अगर यह 'ऑब्जेक्ट' – Grizzly

+0

नहीं है तो संभवतः आपका मतलब है "सी ++ 11 में इसके _xvalues_" के साथ? (पता है कि _xvalues_ और _prvalues_ दोनों _rvalues_ हैं, लेकिन यह _xvalues_ जो C++ 11 के लिए नए हैं, जो महत्वपूर्ण अंतर हैं।) –

1

सी ++ 11 इसे केवल-केवल वस्तुओं के साथ उपयोगी बनाता है। उदाहरण के लिए:

const std::unique_ptr<T> myFunc(); 

unique_ptr एक प्रकार है कि कॉपी नहीं किया जा सकता है; इसे केवल स्थानांतरित किया जा सकता है। लेकिन आप पर const प्रकार पर कॉल नहीं कर सकते हैं। इसलिए, इस स्टोर करने के लिए एक ही रास्ता एक const& या const&& साथ है:

const std::unique_ptr<T> &ptr = myFunc(); 

चूंकि यह एक const unique_ptr है, यह से स्थानांतरित नहीं किया जा सकता है। न ही इसकी प्रतिलिपि बनाई जा सकती है। जिसका अर्थ है कि यह बहुत वास्तव में कहीं भी लंबे समय तक स्टोर करना मुश्किल है। आप इसे ढेर पर रख सकते हैं। लेकिन इसे एक वर्ग का सदस्य बनाना असंभव है (अपरिभाषित व्यवहार का आह्वान किए बिना)।

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

बेशक, यह कॉलर के मूल्य को वापस करने के लिए भी मुश्किल बनाता है। तो डाउनसाइड्स हैं।

+1

क्षमा करें, लेकिन मुझे इसे कम करना होगा - सबसे पहले, आप * चर * -term - विशेष रूप से एक वैश्विक या कार्य-स्थैतिक या थ्रेड-स्थानीय चर में। दूसरा, भले ही रावल्यू स्थानीय संदर्भ से जुड़ा हुआ हो, इसका मतलब यह नहीं है कि वह फ़ंक्शन प्रोग्राम के अंत तक नहीं चलता है। तीसरा, कॉलर का जीवन कठिन बनाना एक बेहद मूर्ख बात है। और चौथा, एक 'unique_ptr' बना रहा है जो अपनी पॉइन्टे को हटा नहीं देता है - आपको बस यह सुनिश्चित करना होगा कि पॉइंटर उसे पॉइंटर (उदाहरण के लिए एक वैश्विक) से बाहर कर देगा। आपका डिवाइस इस गारंटी के साथ मदद नहीं करता है। – jpalecek

+0

प्रतीक्षा करें wat? क्या आप एक अस्थायी के संदर्भ को संग्रहीत कर रहे हैं जिसे तुरंत नष्ट कर दिया गया है? क्या यह संकलन भी करता है? –

+2

@EmilyL। एक अस्थायी के लिए एक संदर्भ संदर्भ अपने जीवनकाल का विस्तार कर सकते हैं, https://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/ देखें – tomjakubowski

संबंधित मुद्दे