क्या C ++ में ऑटो के साथ चर घोषित करने के लिए एक नकारात्मक पहलू है?


143

ऐसा लगता है कि autoC ++ 11 में जोड़ा जाने वाला एक काफी महत्वपूर्ण फीचर था जो बहुत सी नई भाषाओं का अनुसरण करता है। पाइथन जैसी भाषा के साथ, मैंने कोई स्पष्ट चर घोषणा नहीं देखी है (मुझे यकीन नहीं है कि यह पायथन मानकों का उपयोग करना संभव है)।

autoस्पष्ट रूप से घोषित करने के बजाय चर घोषित करने के लिए उपयोग करने में कोई कमी है ?


1
इन्हें भी देखें: stackoverflow.com/questions/6434971/… , stackoverflow.com/questions/15254461/… , stackoverflow.com/questions/6900459/… , stackoverflow.com/questions-8430053/is-c11-auto-type-dangerous , और शायद अन्य। सुनिश्चित नहीं हैं कि ये सटीक डुप्लिकेट हैं, लेकिन वे निश्चित रूप से उम्मीदवार हैं।
कोड़ी ग्रे

3
एकमात्र नकारात्मक पहलू मुझे तब मिला जब मुझे एक कोड बेस को एक (कंसोल) प्लेटफ़ॉर्म पर पोर्ट करना था जिसका कंपाइलर समर्थन नहीं करता था (और समर्थन करने का कोई इरादा नहीं था) C ++ 11 सुविधाएँ!
सैम

7
बस पूर्णता GotW # 94 "लगभग हमेशा ऑटो" के लिए: herbsutter.com/2013/08/12/...
रिचर्ड Critten

1
मैं cppcast सुन रहा था और वहाँ संघर्ष b / w ऑटो और सूची initializers का उल्लेख था। मैं उस पॉडकास्ट को खोजने की कोशिश करूंगा।
अभिनव गौनियाल १४'१६ को

2
पहले नकारात्मक पक्ष यह है मुझे लगता है कि कोड की पठनीयता प्रभावित कर रहा है
ggrr

जवाबों:


111

आपने केवल कमियों के बारे में पूछा है, इसलिए मैं उनमें से कुछ को उजागर कर रहा हूं। जब अच्छी तरह से उपयोग किया जाता है, तो autoकई फायदे भी होते हैं। कमियां दुरुपयोग का परिणाम है, और कोड के लिए वृद्धि की क्षमता से अनपेक्षित तरीके से व्यवहार करने के लिए।

मुख्य दोष यह है कि, उपयोग करके auto, आप जरूरी नहीं जानते कि किस प्रकार की वस्तु बनाई जा रही है। ऐसे अवसर भी होते हैं, जहां प्रोग्रामर कंपाइलर से एक प्रकार की कटौती की उम्मीद कर सकता है, लेकिन कंपाइलर adamantly दूसरे को घटा देता है।

जैसे एक घोषणा पत्र दिया

auto result = CallSomeFunction(x,y,z);

आपको जरूरी नहीं कि किस प्रकार resultका ज्ञान है। यह एक हो सकता है int। यह एक संकेतक हो सकता है। यह कुछ और हो सकता है। वे सभी विभिन्न अभियानों का समर्थन करते हैं। आप नाटकीय रूप से कोड को मामूली परिवर्तन द्वारा भी बदल सकते हैं

auto result = CallSomeFunction(a,y,z);

क्योंकि, CallSomeFunction()परिणाम के प्रकार के लिए जो अधिभार मौजूद हैं, उसके आधार पर पूरी तरह से अलग हो सकता है - और बाद में कोड इसलिए पूरी तरह से अलग उद्देश्य से व्यवहार कर सकते हैं। आप बाद के कोड में अचानक त्रुटि संदेशों को ट्रिगर कर सकते हैं (उदाहरण के लिए बाद में एक डीरेंशन करने की कोशिश कर रहा है int, जो अब कुछ बदलने की कोशिश कर रहा है const)। अधिक भयावह परिवर्तन वह है जहां आपका परिवर्तन संकलक के अतीत को पार करता है, लेकिन बाद में कोड अलग और अज्ञात - संभवतः छोटी गाड़ी - तरीके से व्यवहार करता है।

कुछ चरों के प्रकार का स्पष्ट ज्ञान न होना इसलिए कठिनता से एक दावे को सही ठहराता है जो कोड के अनुसार काम करता है। इसका अर्थ है उच्च-महत्वपूर्णता (जैसे सुरक्षा-महत्वपूर्ण या मिशन-महत्वपूर्ण) डोमेन में "उद्देश्य के लिए फिट" के दावों को सही ठहराने का अधिक प्रयास।

अन्य, अधिक सामान्य दोष, प्रोग्रामर के लिए autoकोड को संकलित करने के लिए एक कुंद साधन के रूप में उपयोग करने का प्रलोभन है , बजाय कोड क्या कर रहा है, इसके बारे में सोचने के बजाय, और इसे सही करने के लिए काम कर रहा है।


58
यह ध्यान रखना दिलचस्प है कि यदि इस तरह के उदाहरणों का उपयोग करने की खामी है auto, तो अधिकांश बतख-टाइप भाषा डिजाइन द्वारा इस तरह की खामी का सामना करती है!
लेबेन अस

11
यदि CallSomeFunction()इसके तर्कों के अनुक्रम के आधार पर एक अलग प्रकार लौटाता है, तो इसका एक दोष है CallSomeFunction(), न कि एक समस्या का auto। अगर आप किसी ऐसे फंक्शन का डॉक्यूमेंटेशन नहीं पढ़ रहे हैं, जिसे आप इस्तेमाल करने से पहले इस्तेमाल कर रहे हैं, तो यह प्रोग्रामर का दोष है, समस्या का नहीं auto। - लेकिन मैं समझता हूं कि आप यहां शैतान के वकील की भूमिका निभा रहे हैं, यह सिर्फ इतना है कि Nir Friedman के पास ज्यादा बेहतर मामला है।
देवसोलर

16
@DevSolar: T CallSomeFunction(T, int, int)एक डिजाइन दोष क्यों होगा ? स्पष्ट रूप से यह "अपने तर्कों के अनुक्रम के आधार पर एक अलग प्रकार देता है।"
8

9
"मुख्य दोष यह है कि, उपयोग करके auto, आप जरूरी नहीं जानते कि किस प्रकार की वस्तु बनाई जा रही है।" क्या आप इस बारे में विस्तार से बता सकते हैं कि यह समस्या क्यों है auto, और सब-डेफिसिट टेम्पोररी की समस्या नहीं है? क्यों auto result = foo();बुरा है, लेकिन foo().bar()नहीं?
Angew को SO SO

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

76

यह autoबिल्कुल राजसी तरीके से कमियां नहीं है, लेकिन व्यावहारिक रूप से यह कुछ के लिए एक मुद्दा है। मूल रूप से, कुछ लोग या तो: a) autoप्रकारों के लिए एक रक्षक के रूप में व्यवहार करते हैं और इसका उपयोग करते समय अपने मस्तिष्क को बंद कर देते हैं, या b) autoयह भूल जाते हैं कि हमेशा मूल्य प्रकारों के लिए कटौती होती है। इसके कारण लोग इस तरह की चीजें करते हैं:

auto x = my_obj.method_that_returns_reference();

उफ़, हमने बस किसी वस्तु की गहरी नकल की है। यह अक्सर बग या प्रदर्शन विफल रहता है। फिर, आप दूसरे तरीके से भी स्विंग कर सकते हैं:

const auto& stuff = *func_that_returns_unique_ptr();

अब आपको झूलने का संदर्भ मिलता है। ये समस्याएँ बिलकुल भी नहीं हैं auto, इसलिए मैं इसके खिलाफ वैध तर्क नहीं मानता। लेकिन ऐसा लगता है autoकि इन मुद्दों को मैं (मेरे व्यक्तिगत अनुभव से) अधिक सामान्य बनाता हूं, जिन कारणों से मैंने शुरुआत में सूचीबद्ध किया था।

मुझे लगता है कि दिया गया समय लोगों को समायोजित करेगा, और श्रम के विभाजन को समझेगा: autoअंतर्निहित प्रकार को घटाता है, लेकिन आप अभी भी संदर्भ-नेस और कास्ट-नेस के बारे में सोचना चाहते हैं। लेकिन इसमें थोड़ा समय लग रहा है।


आप किसी महंगी वस्तु को शुरू करने के लिए गहरी-कॉपी क्यों कर सकते हैं?
लॉरेंट ला रिज़्ज़ा

3
@LaurentLARIZZA: कुछ वर्गों में कॉपी कंस्ट्रक्टर केवल इसलिए होते हैं क्योंकि उन्हें कभी-कभी ज़रूरत होती है (जैसे, उदाहरण std::vector)। नकल करना महंगा होने के कारण एक वर्ग की संपत्ति नहीं है, बल्कि व्यक्तिगत वस्तुओं की है। तो method_that_returns_referenceहो सकता है कि किसी वर्ग की एक ऐसी वस्तु का उल्लेख हो, जिसमें एक कॉपी कंस्ट्रक्टर हो, लेकिन जो वस्तु कॉपी करने के लिए काफी महंगी होती है (और उसे स्थानांतरित नहीं किया जा सकता है)।
मार्क वैन लीउवेन

@MarcvanLeeuwen: यदि ऑब्जेक्ट कॉपी करना महंगा है, और इससे स्थानांतरित नहीं किया जा सकता है, तो इसे एक में क्यों संग्रहीत किया जाएगा std::vector? (क्योंकि यह हो सकता है, हाँ, या क्योंकि आप कक्षा को नियंत्रित नहीं करते हैं, लेकिन यह बात नहीं है) यदि यह कॉपी करना महंगा है, (और कोई संसाधन नहीं है, क्योंकि यह प्रतिलिपि योग्य है), तो ऑब्जेक्ट पर गाय का उपयोग क्यों नहीं किया जाता है? डेटा स्थानीयता पहले से ही ऑब्जेक्ट के आकार से मारा जाता है।
लॉरेंट ला रिज़्ज़ा

2
@LaurentLARIZZA एक वेक्टर में संग्रहित कुछ का एक उदाहरण महंगा नहीं है, सिर्फ एक नियमित उदाहरण के लिए वेक्टर <डबल> कॉपी करना महंगा है, यह एक ढेर आवंटन + ओ (एन) काम है। मूविंग एक रेड हेरिंग है। मैंने जो पहली पंक्ति दिखाई, वह कॉपी होगी, न कि चलती है, जब तक कि लौटाया गया संदर्भ एक संदर्भ नहीं है। गाय वास्तव में न तो यहां है और न ही है। तथ्य यह है कि वस्तुओं की नकल करना महंगा हमेशा मौजूद रहेगा।
निर फ्राइडमैन

4
@ यह सुरक्षित रूप से ऐसा नहीं कर सकता, क्योंकि यह टुकड़ा कर सकता है। केवल सुरक्षित चीज यह कर सकती है = deleteकि अधिभार। हालांकि आमतौर पर आप जो कहते हैं वह एक समाधान है। यह एक ऐसा विषय है जिसे मैंने खोजा है, यदि आप रुचि रखते हैं: nirfriedman.com/2016/01/18/…
निर फ्राइडमैन

51

अन्य उत्तर कमियों का उल्लेख कर रहे हैं जैसे "आप वास्तव में नहीं जानते कि एक चर का प्रकार क्या है।" मैं कहूंगा कि यह कोड में नामकरण सम्मेलन से काफी हद तक संबंधित है। यदि आपके इंटरफेस स्पष्ट रूप से नामित हैं, तो आपको यह ध्यान रखने की आवश्यकता नहीं है कि सटीक प्रकार क्या है। यकीन है, auto result = callSomeFunction(a, b);आपको बहुत कुछ नहीं बताता है। लेकिन auto valid = isValid(xmlFile, schema);आपको यह बताने के लिए पर्याप्त है validकि इसका सही प्रकार क्या है, इसकी परवाह किए बिना उपयोग करें । सब के बाद, बस के साथ if (callSomeFunction(a, b)), आप या तो प्रकार नहीं जानते होंगे। किसी भी अन्य उपसमुच्चय अस्थायी वस्तुओं के साथ भी ऐसा ही है। इसलिए मैं इसे असली कमी नहीं मानता auto

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

SomeType operator* (const Matrix &lhs, const Vector &rhs);

तार्किक रूप से, हम उम्मीद करेंगे SomeTypeहोने के लिए Vector, और हम निश्चित रूप से हमारे कोड में इस तरह के रूप में यह इलाज के लिए चाहते हैं। हालांकि, यह संभव है कि अनुकूलन उद्देश्यों के लिए, बीजगणित पुस्तकालय हम अभिव्यक्ति अभिव्यक्ति टेम्पलेट्स का उपयोग कर रहे हैं, और वास्तविक वापसी प्रकार यह है:

MultExpression<Matrix, Vector> operator* (const Matrix &lhs, const Vector &rhs);

अब, समस्या यह है कि MultExpression<Matrix, Vector>सभी संभावना में एक const Matrix&और const Vector&आंतरिक रूप से स्टोर करेगा ; यह उम्मीद करता है कि यह Vectorअपनी पूर्ण अभिव्यक्ति के अंत से पहले परिवर्तित हो जाएगा । यदि हमारे पास यह कोड है, तो सब कुछ ठीक है:

extern Matrix a, b, c;
extern Vector v;

void compute()
{
  Vector res = a * (b * (c * v));
  // do something with res
}

हालांकि, अगर हमने यहां इस्तेमाल किया था, तो हम autoपरेशानी में पड़ सकते हैं:

void compute()
{
  auto res = a * (b * (c * v));
  // Oops! Now `res` is referring to temporaries (such as (c * v)) which no longer exist
}

3
@NirFriedman आप सही हैं यह मजबूत है, लेकिन मुझे वास्तव में लगता है कि autoइसमें बहुत कमियां हैं, इसलिए मैं उस ताकत से खड़ा हूं। और परदे के पीछे के अन्य उदाहरणों में विभिन्न "स्ट्रिंग बिल्डरों" और डीएसएल में पाए जाने वाले समान ऑब्जेक्ट शामिल हैं।
Angew अब SO

2
मुझे एक्सप्रेशन टेम्प्लेट द्वारा और autoपहले, विशेष रूप से Eigen लाइब्रेरी के साथ काट दिया गया है । यह विशेष रूप से मुश्किल है क्योंकि समस्या अक्सर डिबग बिल्ड में दिखाई नहीं देती है।
डैन

1
उपयोग की autoका उपयोग करते समय भी काट सकते हैं वर्मी मैट्रिक्स पुस्तकालय है, जो अनुकूलन प्रयोजनों के लिए टेम्पलेट मेटा प्रोग्रामिंग का गहन उपयोग करता। सौभाग्य से डेवलपर्स ने .eval () फ़ंक्शन को जोड़ा है, जिसका उपयोग समस्याओं से बचने के लिए किया जा सकता हैauto
mtall

2
"यदि आपके इंटरफेस स्पष्ट रूप से नामित हैं, तो आपको यह ध्यान रखने की आवश्यकता नहीं है कि सटीक प्रकार क्या है" आपका कंपाइलर चर के नामों का अध्ययन करके आपके कोड की शुद्धता की जांच नहीं कर सकता है। यह एक प्रकार की प्रणाली का संपूर्ण बिंदु है। ब्लाइंडली बाईपास करना मूर्खतापूर्ण है!
ऑर्बिट

1
@Angew: यह अस्थायी लोगों के लिए कोई समस्या नहीं है क्योंकि आप आमतौर पर तुरंत उनका उपयोग कर रहे हैं, जिसमें autoआम तौर पर किसी प्रकार का चेक शामिल होता है (और autoहर जगह छप जाना उस प्रकार की सुरक्षा को दूर ले जाता है जैसा कि यह हर जगह होता है)। यह एक अच्छी तुलना नहीं है।
10

13

कमियां में से एक है कि कभी कभी आप यह घोषित नहीं कर सकते हैं const_iteratorके साथ autoइस प्रश्न से लिए गए कोड के उदाहरण में आपको साधारण (नॉन कास्ट) पुनरावृत्ति प्राप्त होगी :

map<string,int> usa;
//...init usa
auto city_it = usa.find("New York");

3
ठीक है, तुम एक मिल iteratorके बाद से अपने नक्शे गैर है किसी भी मामले में const। यदि आप इसे रूपांतरित करना चाहते हैं const_iterator, तो या तो चर प्रकार को हमेशा की तरह स्पष्ट रूप से निर्दिष्ट करें, या एक विधि निकालें ताकि आपका नक्शा आपके संदर्भ में संकुचित हो find। (मैं उत्तरार्द्ध को पसंद करता हूं। एसआरपी।)
लॉरेंट ला रिजजा

auto city_it = static_cast<const auto&>(map).find("New York")? या, C ++ 17 के साथ auto city_if = std::as_const(map).find("New York"),।
देव नल

11

यह आपके कोड को पढ़ने के लिए थोड़ा कठिन या थकाऊ बनाता है। कुछ इस तरह की कल्पना करें:

auto output = doSomethingWithData(variables);

अब, आउटपुट के प्रकार का पता लगाने के लिए, आपको doSomethingWithDataफ़ंक्शन के हस्ताक्षर को ट्रैक करना होगा ।


40
हर बार नहीं। उदाहरण के auto it = vec.begin();लिए पढ़ने के लिए बहुत आसान है std::vector<std::wstring>::iterator it = vec.begin();
जोनाथन पॉटर

4
माना। यह उपयोग के मामले पर निर्भर करता है। मैं इसके बारे में अधिक सटीक हो सकता था।
स्केम

1
@SeeDart हाँ, जो लोग इस तरह से ऑटो का उपयोग कर रहे हैं वे गलत कर रहे हैं।
अक्टूबर को lciamp

6
"फंक्शन सिग्नेचर को ट्रैक करें", यदि वह माउस होवर या कुंजी प्रेस से दूर नहीं है ("सिंबल फॉलो करें" / "डिक्लेरेशन पर जाएं" / जो भी इसे कहा जाता है), आपको अपने एडिटर को और अधिक कॉन्फ़िगर करने की आवश्यकता है या एक आईडीई पर स्विच करें जो कॉन्फ़िगरेशन के बिना ऐसा कर सकता है ... हालांकि आपकी बात अभी भी वैध है।
१३:३३

6
मैंने देखा कि एक आईडीई में नहीं, बल्कि चेक की समीक्षा करते समय डिफरेंशियल के छोटे-छोटे छिद्रों में! ऑटो के साथ वे उस कारण के लिए पढ़ने के लिए कठिन हैं।
JDługosz

10

इस डेवलपर की तरह , मुझे नफरत है auto। या यों कहें, मैं नफरत करता हूं कि लोग कैसे दुरुपयोग करते हैंauto

मैं (मज़बूत) राय हूँ जो autoआपको सामान्य कोड लिखने में मदद करने के लिए है, टाइपिंग कम करने के लिए नहीं
C ++ एक ऐसी भाषा है जिसका लक्ष्य आपको मजबूत कोड लिखना है, कि विकास के समय को कम करना।
यह C ++ की कई विशेषताओं से काफी हद तक स्पष्ट है, लेकिन दुर्भाग्य से कुछ नए जैसे autoकि लोगों को गुमराह करना कम कर देते हैं यह सोचकर कि वे टाइपिंग के साथ आलसी होना शुरू कर दें।

पूर्व autoदिनों में, लोग typedefएस का उपयोग करते थे , जो बहुत अच्छा था क्योंकि typedef पुस्तकालय के डिजाइनर ने आपको यह पता लगाने में मदद की कि रिटर्न प्रकार क्या होना चाहिए, ताकि उनकी लाइब्रेरी उम्मीद के मुताबिक काम करे। जब आप उपयोग करते हैं auto, तो आप कक्षा के डिजाइनर से उस नियंत्रण को हटा लेते हैं और इसके बजाय संकलक से यह पता लगाने के लिए पूछते हैं कि प्रकार क्या होना चाहिए, जो टूलबॉक्स से सबसे शक्तिशाली C ++ टूल में से एक को हटा देता है और उनके कोड को तोड़ता है

आम तौर पर, यदि आप उपयोग करते हैं auto, तो यह इसलिए होना चाहिए क्योंकि आपका कोड किसी भी उचित प्रकार के लिए काम करता है , इसलिए नहीं कि आप उस प्रकार को लिखने के लिए बहुत आलसी हैं, जिसके साथ उसे काम करना चाहिए। यदि आप autoआलस्य की मदद करने के लिए एक उपकरण के रूप में उपयोग करते हैं, तो क्या होता है कि आप अंततः अपने कार्यक्रम में सूक्ष्म कीड़े शुरू करना शुरू करते हैं, आमतौर पर अंतर्निहित रूपांतरणों के कारण होता है जो आपके उपयोग के कारण नहीं हुआ auto

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

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


3
which was great because typedef allowed the designer of the library to help you figure out what the return type should be, so that their library works as expected. When you use auto, you take away that control from the class's designer and instead ask the compiler to figure out what the type should beवास्तव में एक अच्छा कारण IMO नहीं है। उदाहरण के लिए अप-टू-डेट IDE, Visual Studio 2015, आपको ओवर हॉवर करके चर के प्रकार की जांच करने की अनुमति देता है auto। यह * बिल्कुल * एक ही जैसा है typedef
सोमबेरो चिकन

@JameyD: आप वहां कई महत्वपूर्ण बिंदुओं को याद कर रहे हैं: (1) आपका आईडीई तर्क केवल तभी काम करता है जब प्रकार ठोस हो, टेम्प्लेट न हो। आईडीई संभवतः आपको आश्रित प्रकारों के मामले में सही प्रकार नहीं बता सकता है, जैसे typename std::iterator_traits<It>::value_type। (२) संपूर्ण बिंदु यह था कि कोड के पिछले डिजाइनर द्वारा इच्छित सही प्रकार के रूप में अनुमानित प्रकार "वैसा ही" नहीं होना चाहिए; का उपयोग करके auto, आप सही प्रकार निर्दिष्ट करने की डिजाइनर की क्षमता को दूर ले जा रहे हैं।
user541686

आप मूल रूप से प्रॉक्सी के बारे में बात कर रहे हैं, जिसमें से एक उत्तर में पहले से ही उल्लेख है। एक्सप्रेशन टेम्प्लेट और वेक्टर <bool> बकवास ज्यादातर लोगों के लिए रोजमर्रा का कोड नहीं है। ज्यादातर स्थितियों में, आप निहित रूपांतरण नहीं चाहते हैं, और ऑटो उस के साथ मदद करता है। हर्ब सटर अपने एक ब्लॉग पोस्ट में बड़े पैमाने पर ऑटो के फायदों के बारे में बात करता है, और यह ज्यादातर कीस्ट्रोक्स के बारे में नहीं है, और यह केवल सामान्य कोड के लिए भी नहीं है। इसके अलावा, आपके द्वारा प्रदान किया गया पहला लिंक, ब्लॉग पोस्ट बस भयानक सलाह है (यही कारण है कि उसकी टिप्पणी अनुभाग में मुखर रूप से आलोचना की गई है)।
निर फ्राइडमैन

@NirFriedman: "... vector<bool>बकवास" ... क्षमा करें? आपको क्या लगता bitsetहै कि इसे कैसे लागू किया जाता है? या क्या आप बिट कंटेनर को पूरी तरह से बकवास मानते हैं ?!
user541686

1
@NirFriedman: वेक्टर के बारे में कुछ भी नहीं <bool> मेरे लिए समाचार है। जो मैं आपको बताने की कोशिश कर रहा हूं और जिसे आप स्पष्ट रूप से समझने से इंकार कर रहे हैं, वह यह है कि इस प्रश्न के लिए बिटसेट वेक्टर <bool> से अलग नहीं है - दोनों ही प्रॉक्सी का उपयोग करते हैं, क्योंकि प्रॉक्सी को उपयोगी माना जाता था , और तथ्य यह है कि परदे के पीछे उपयोगी होते हैं एक वास्तविकता है जिसे आपको अस्वीकार करने के बजाय जीने की आवश्यकता है। क्या आप कृपया इसे बहस में बदलना बंद कर सकते हैं कि क्या आपको लगता है कि परदे के पीछे उपयोगी हैं? यह बहस का विषय नहीं है, और यह भी, उन पर आपकी राय सिर्फ आपकी राय है, किसी तरह का तथ्य नहीं।
user541686

6

autoप्रति से कमियां नहीं हैं , और मैं नए कोड में हर जगह इसका (हाथ से लहराते) उपयोग करने की वकालत करता हूं। यह आपके कोड को लगातार टाइप-चेक करने की अनुमति देता है, और लगातार चुप रहने से बचता है। (यदि अचानक से लौटने वाला एक फ़ंक्शन और उससे Bप्राप्त होता है , तो उसके वापसी मूल्य को संग्रहीत करने की उम्मीद के अनुसार व्यवहार करता है)AABauto

हालांकि, पूर्व-सी ++ 11 विरासत कोड स्पष्ट रूप से टाइप किए गए चर के उपयोग से प्रेरित निहित रूपांतरणों पर भरोसा कर सकता है। स्पष्ट रूप से टाइप किया गया चर autoबदलना कोड व्यवहार को बदल सकता है , इसलिए आप बेहतर सतर्क रहेंगे।


डाउनवोटिंग उचित है, लेकिन क्या आप कृपया इस पर टिप्पणी कर सकते हैं?
लॉरेंट ला रिज़्ज़ा

मैंने आपको कम नहीं किया, लेकिन autoप्रति से कमियां हैं (या कम से कम - कई लोगों को लगता है कि यह करता है)। इस पैनल चर्चा में दूसरे प्रश्न में दिए गए उदाहरण पर विचार करें जिसमें सटर, अलेक्जेंड्रेस्क्यू और मेयर्स के साथ: यदि आपके पास है auto x = foo(); if (x) { bar(); } else { baz(); }और foo()रिटर्न bool- foo()एक एनुम (दो के बजाय तीन विकल्प) वापस करने पर क्या होता है ? autoकोड काम करने के लिए जारी है, लेकिन अप्रत्याशित परिणाम देगा।
einpoklum

@einpoklum: और एक अनकही एनम के मामले में कुछ भी बदलने के boolबजाय का उपयोग करता है auto? मैं गलत हो सकता हूं (यहां जांच नहीं कर सकता), लेकिन मुझे लगता है कि अंतर केवल यह है कि परिवर्तन boolकी स्थिति के मूल्यांकन के बजाय परिवर्तनशील घोषणा में होता है if। यदि enumस्कोप है, तो boolएक स्पष्ट नोटिस के बिना रूपांतरण नहीं होगा।
लॉरेंट ला रिज़ज़ा

4

कीवर्ड autoकेवल वापसी मान से प्रकार घटाते हैं। इसलिए, यह पायथन ऑब्जेक्ट के साथ समतुल्य नहीं है, जैसे

# Python
a
a = 10       # OK
a = "10"     # OK
a = ClassA() # OK

// C++
auto a;      // Unable to deduce variable a
auto a = 10; // OK
a = "10";    // Value of const char* can't be assigned to int
a = ClassA{} // Value of ClassA can't be assigned to int
a = 10.0;    // OK, implicit casting warning

चूंकि autoसंकलन के दौरान कटौती की जाती है, इसलिए रनटाइम पर इसका कोई दोष नहीं होगा।


1
हाँ, यह मूल रूप type()से अजगर में क्या करता है। यह प्रकार घटाता है, यह उस प्रकार का नया चर नहीं बनाता है।
lciamp

2
@lciamp वास्तव में, यह होगा decltypeautoविशेष रूप से चर असाइनमेंट के लिए है।
घन

4

यहाँ अब तक किसी ने क्या उल्लेख किया है, लेकिन अगर आपने मुझसे पूछा है, तो खुद ही जवाब देने लायक है।

चूंकि (भले ही हर किसी को पता होना चाहिए कि C != C++ सी में लिखे कोड आसानी से सी ++ संगत होना भी बहुत प्रयास के बिना तैयार किया जा ++ कोड सी के लिए एक आधार प्रदान करने के लिए तैयार किया जा सकता है और इसलिए), इस डिजाइन के लिए एक आवश्यकता हो सकती है।

मुझे कुछ नियमों के बारे में पता है जहां से कुछ अच्छी तरह से परिभाषित निर्माण Cअवैध हैं C++और इसके विपरीत। लेकिन यह बस टूटी हुई निष्पादनयोग्यताओं में परिणत होता है और ज्ञात यूबी-क्लॉज लागू होता है जो ज्यादातर बार अजीबोगरीब खामियों को देखते हैं जिसके परिणामस्वरूप क्रैश या जो भी (या यहां तक ​​कि अनिर्धारित रह सकता है, लेकिन यहां कोई फर्क नहीं पड़ता)।

लेकिन autoपहली बार है 1 यह परिवर्तन होता है!

कल्पना कीजिए कि आपने autoपहले स्टोर-क्लास स्पेसियर के रूप में इस्तेमाल किया था और कोड ट्रांसफर किया था। यह जरूरी भी नहीं होगा (जिस तरह से इसका इस्तेमाल किया गया था उसके आधार पर) "ब्रेक"; यह वास्तव में चुपचाप कार्यक्रम के व्यवहार को बदल सकता है।

यह कुछ ऐसा है जिसे ध्यान में रखना चाहिए।


1 कम से कम पहली बार मुझे पता चला है।


1
संकलन करने का प्रयास करने पर आपको वैसे भी एक कंपाइलर त्रुटि मिलेगी।
सोम्ब्रेरो चिकन

@JameyD: ऐसा क्या होगा? अलग-अलग अर्थ वाले 2 मान्य कोड स्थितियों को कभी त्रुटि में फिर से बदलना क्यों चाहिए?
धिन

8
यदि आप intC में "कोई प्रकार का तात्पर्य नहीं" पर भरोसा कर रहे हैं , तो आप सभी खराब सामानों के लायक हैं जो आपको इससे प्राप्त होंगे। और यदि आप इस पर भरोसा नहीं कर रहे हैं, तो एक प्रकार के साथauto एक स्टोरेज क्लास स्पेसियर के रूप में उपयोग करने से आपको C ++ (जो इस मामले में एक अच्छी बात है) में एक अच्छा संकलन त्रुटि देगा।
Angew को अब SO

1
@ अच्छी तरह से मैं जिस मामले का उल्लेख कर रहा हूँ, वह हाँ है। मैं यह नहीं कर रहा हूं । लेकिन यह कुछ ऐसा है जिसे कम से कम ध्यान में रखा जाना चाहिए।
dhein

3

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


1
वहाँ static_cast है, और उदाहरण मेयर्स 'प्रभावी आधुनिक सी के लिए IIRC ++ यहां तक कि इसे उपयोग करने की सलाह ऑटो टाइप चर के लिए प्रकार निर्दिष्ट करने।
हाइड

2

जैसा कि मैंने वर्णन किया है इस उत्तर auto कभी-कभी ऐसी कायरतापूर्ण स्थितियों का परिणाम हो सकता है जो आपने इरादा नहीं किया था। आपको यह कहना होगा कि auto&केवल autoएक पॉइंटर टाइप बना सकते हैं। यह सब एक साथ विनिर्देशक को छोड़ कर भ्रम की स्थिति पैदा कर सकता है, जिसके परिणामस्वरूप वास्तविक संदर्भ के बजाय संदर्भ की एक प्रति प्राप्त होती है।


2
वह फंकी नहीं है। यही कारण है कि auto, एक संदर्भ का उल्लेख नहीं है और न ही constप्रकार। एक autoसंदर्भ के लिए, आप बेहतर उपयोग करेंगे auto&&। (एक सार्वभौमिक संदर्भ) यदि संसाधन की प्रतिलिपि बनाने या उसके स्वामित्व के लिए प्रकार सस्ता नहीं है, तो शुरू करने के लिए प्रकार को प्रतिलिपि योग्य नहीं होना चाहिए।
लॉरेंट ला रिज़्ज़ा

1

एक और परेशान उदाहरण:

for (auto i = 0; i < s.size(); ++i)

एक चेतावनी ( comparison between signed and unsigned integer expressions [-Wsign-compare]) उत्पन्न करता है , क्योंकि iएक हस्ताक्षरित इंट है। इससे बचने के लिए आपको उदा

for (auto i = 0U; i < s.size(); ++i)

या शायद बेहतर:

for (auto i = 0ULL; i < s.size(); ++i)

1
हाँ मुझे यह एक परेशान सा लगता है। लेकिन भाषा का छेद कहीं और है। इस कोड को वास्तव में पोर्टेबल होने के लिए, sizeरिटर्न मानते हुए size_t, आपको एक size_tशाब्दिक की तरह सक्षम होना होगा 0z। लेकिन आप ऐसा करने के लिए यूडीएल की घोषणा कर सकते हैं। ( size_t operator""_z(...))
लॉरेंट ला रिजज़ा

1
विशुद्ध रूप से सैद्धांतिक आपत्तियां: मुख्य रूप से मुख्यधारा के आर्किटेक्चर पर unsignedसभी मूल्यों को धारण करने के लिए लगभग बहुत बड़ा नहीं होने की संभावना है std::size_t, इसलिए इस अप्रत्याशित घटना में कि किसी के पास तत्वों की एक बेतुकी विशाल संख्या के साथ एक कंटेनर था, unsignedजो कम सीमा पर एक अनंत लूप का कारण बन सकता है। सूचकांकों के। हालांकि यह एक समस्या होने की संभावना नहीं है, std::size_tइसका उपयोग स्वच्छ कोड प्राप्त करने के लिए किया जाना चाहिए जो ठीक से इरादे का संकेत देता है। मुझे यकीन नहीं है कि unsigned long longपर्याप्त रूप से पर्याप्त रूप से पर्याप्त होने की गारंटी है, हालांकि व्यवहार में यह समान होना चाहिए।
अंडरस्कोर_ड

@underscore_d: हाँ, निष्पक्ष बिंदु - unsigned long longकम से कम 64 बिट होने की गारंटी है, लेकिन सिद्धांत रूप में size_tयह इससे बड़ा हो सकता है, मुझे लगता है। बेशक अगर आपके कंटेनर में 2 ^ 64 तत्व हैं तो आपको चिंता करने की बड़ी समस्या हो सकती है ... ;-)
पॉल आर

1

मुझे लगता autoहै कि स्थानीय संदर्भ में उपयोग किए जाने पर अच्छा लगता है, जहां पाठक आसानी से और स्पष्ट रूप से अपने प्रकार में कटौती कर सकता है, या इसके प्रकार की टिप्पणी या वास्तविक प्रकार का पता लगाने वाले नाम के साथ अच्छी तरह से प्रलेखित किया जा सकता है। जिन लोगों को यह समझ में नहीं आता है कि यह कैसे काम करता है, वे इसे गलत तरीकों से ले सकते हैं, जैसे कि templateया इसके बजाय इसका उपयोग करना । यहाँ मेरी राय में कुछ अच्छे और बुरे उपयोग के मामले हैं।

void test (const int & a)
{
    // b is not const
    // b is not a reference

    auto b = a;

    // b type is decided by the compiler based on value of a
    // a is int
}

अच्छा उपयोग करता है

iterators

std::vector<boost::tuple<ClassWithLongName1,std::vector<ClassWithLongName2>,int> v();

..

std::vector<boost::tuple<ClassWithLongName1,std::vector<ClassWithLongName2>,int>::iterator it = v.begin();

// VS

auto vi = v.begin();

कार्य बिंदु

int test (ClassWithLongName1 a, ClassWithLongName2 b, int c)
{
    ..
}

..

int (*fp)(ClassWithLongName1, ClassWithLongName2, int) = test;

// VS

auto *f = test;

खराब उपयोग

डाटा प्रवाह

auto input = "";

..

auto output = test(input);

समारोह हस्ताक्षर

auto test (auto a, auto b, auto c)
{
    ..
}

तुच्छ मामले

for(auto i = 0; i < 100; i++)
{
    ..
}

जब आप एक चाहते हैं int, तो आपको एक और चार टाइप करना होगा यदि आप जाते हैं auto। यह अस्वीकार्य है
Rerito

@Rerito हाँ, यह एक intआसानी से यहाँ देखा और टाइपिंग intकम है। इसलिए यह एक तुच्छ मामला है।
खालिद.के

0

मुझे आश्चर्य है कि किसी ने भी इसका उल्लेख नहीं किया है, लेकिन मान लीजिए कि आप किसी चीज़ के तथ्य की गणना कर रहे हैं:

#include <iostream>
using namespace std;

int main() {
    auto n = 40;
    auto factorial = 1;

    for(int i = 1; i <=n; ++i)
    {
        factorial *= i;
    }

    cout << "Factorial of " << n << " = " << factorial <<endl;   
    cout << "Size of factorial: " << sizeof(factorial) << endl; 
    return 0;
}

यह कोड इसका उत्पादन करेगा:

Factorial of 40 = 0
Size of factorial: 4

यह निश्चित रूप से अपेक्षित परिणाम नहीं था। ऐसा इसलिए हुआ क्योंकि autoचर फैक्टरियल के प्रकार को घटा intदिया गया क्योंकि इसे सौंपा गया था 1

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