सी ++ की छिपी विशेषताएं? [बन्द है]


114

कोई सी ++ प्यार नहीं करता है जब यह प्रश्नों की "छिपी हुई विशेषताएं" की बात आती है? लगा कि मैं इसे वहीं फेंक दूंगा। C ++ की कुछ छिपी हुई विशेषताएँ क्या हैं?


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

5
@ लिट जे: बहुत से लोगों ने 786-पृष्ठ आईएसओ सी ++ मानक को कवर से कवर करने के लिए नहीं पढ़ा है - लेकिन मुझे लगता है कि आपके पास है, और आपने इसे सही बनाए रखा है?
j_random_hacker

2
@Laith, @j_random: मेरा प्रश्न देखें "एक प्रोग्रामर का मज़ाक क्या है, मैं इसे कैसे पहचानता हूं, और stackoverflow.com/questions/1/you-have-been-link-rolled पर क्या उचित प्रतिक्रिया है" ।

देखें meta.stackexchange.com/questions/56669/... , meta.stackexchange.com/questions/57226/... और संबंधित मेटा पोस्ट।

जवाबों:


308

अधिकांश C ++ प्रोग्रामर टर्नरी ऑपरेटर से परिचित हैं:

x = (y < 0) ? 10 : 20;

हालांकि, उन्हें इस बात का एहसास नहीं है कि इसका इस्तेमाल एक लवलीन के रूप में किया जा सकता है:

(a == 0 ? a : b) = 1;

जिसके लिए आशुलिपि है

if (a == 0)
    a = 1;
else
    b = 1;

सावधानी से प्रयोग करें :-)


11
बहुत ही रोचक। मैं देख सकता हूँ कि कुछ अपठनीय कोड बना रहा हूँ।
जेसन बेकर

112
ओह। (a == 0; a: b) = (y <0; 10: 20);
जैस्पर बेकर्स

52
(b? trueCount: falseCount) ++
पावेल

12
डननो अगर यह जीसीसी विशिष्ट है, लेकिन मुझे यह देखकर आश्चर्य हुआ कि यह भी काम किया है (value ? function1 : function2)():।
क्रिस बर्ट-ब्राउन

3
@ क्रिस बर्ट-ब्राउन: नहीं, अगर वे एक ही प्रकार (यानी कोई डिफ़ॉल्ट तर्क नहीं है) हर जगह काम करना चाहिए function1और function2फ़ंक्शन बिंदुओं में परिवर्तित कर दिया जाता है, और परिणाम को वापस बदल दिया जाता है।
MSALERS

238

आप URI को बिना त्रुटि के C ++ स्रोत में डाल सकते हैं। उदाहरण के लिए:

void foo() {
    http://stackoverflow.com/
    int bar = 4;

    ...
}

41
लेकिन केवल एक समारोह में, मुझे संदेह है? :)
कांस्टेंटिन

51
@jpoh: http के बाद कोलन एक "लेबल" बन जाता है जिसे आप बाद में एक गोटो स्टेटमेंट में उपयोग करते हैं। आपको अपने संकलक से वह चेतावनी मिलती है क्योंकि उपरोक्त उदाहरण में किसी भी गोटो बयान में इसका उपयोग नहीं किया गया है।
utku_karatas 17

9
आप एक से अधिक जोड़ सकते हैं जब तक कि उनके पास अलग-अलग प्रोटोकॉल हों! ftp.microsoft.com गोफर: //aerv.nl/1 और इतने पर ...
डैनियल Earwicker

4
@ पावेल: एक पहचानकर्ता जिसके बाद कोलन होता है, एक लेबल होता है (उपयोग के लिए goto, जो C ++ के पास है)। दो स्लैश के बाद कुछ भी एक टिप्पणी है। इसलिए, के साथ http://stackoverflow.com, httpएक लेबल है (आप सैद्धांतिक रूप से लिख सकते हैं goto http;), और //stackoverflow.comबस एक अंत-पंक्ति टिप्पणी है। ये दोनों कानूनी C ++ हैं, इसलिए निर्माण संकलित करता है। यह निश्चित रूप से उपयोगी कुछ भी नहीं करता है।
डेविड थॉर्नले

8
दुर्भाग्य से goto http;वास्तव में URL का अनुसरण नहीं करता है। :(
याकोव गल्का

140

सूचक अंकगणित।

C ++ प्रोग्रामर उन बग्स से बचने के लिए पसंद करते हैं, जो बग को पेश किए जा सकते हैं।

सबसे अच्छा C ++ मैंने कभी देखा है? एनालॉग शाब्दिक।


11
हम बग के कारण संकेत से बचते हैं? संकेत मूल रूप से गतिशील C ++ कोडिंग के बारे में सब कुछ हैं!
निक बेडफोर्ड

1
एनालॉग सीमेंल्स, सी + + कॉन्टेस्ट एंट्रीज़ के लिए बहुत बढ़िया हैं, खासकर ASCII- आर्ट टाइप।
सिंथेट

119

मैं वहां के अधिकांश पदों से सहमत हूं: C ++ एक बहु-प्रतिमान भाषा है, इसलिए "छिपी हुई" विशेषताएँ जो आपको मिलेंगी ("अपरिभाषित व्यवहारों के अलावा" जो आपको हर कीमत पर बचनी चाहिए) सुविधाओं के चतुर उपयोग हैं।

उन सुविधाओं में से अधिकांश भाषा की सुविधाओं में निर्मित नहीं हैं, लेकिन पुस्तकालय आधारित हैं।

सबसे महत्वपूर्ण RAII है , जिसे अक्सर C ++ डेवलपर्स द्वारा सी दुनिया से आने वाले वर्षों के लिए अनदेखा किया जाता है। ऑपरेटर ओवरलोडिंग अक्सर एक गलतफहमी की विशेषता होती है जो सरणी-जैसे व्यवहार (सबस्क्रिप्ट ऑपरेटर), सूचक जैसे संचालन (स्मार्ट पॉइंटर्स) और बिल्ड-इन-समान संचालन (मैट्रिसेस को गुणा करना) को सक्षम करता है।

अपवाद का उपयोग अक्सर मुश्किल होता है, लेकिन कुछ काम के साथ, अपवाद सुरक्षा के माध्यम से वास्तव में मजबूत कोड का उत्पादन कर सकते हैं विशिष्टताओं (कोड सहित, जो विफल नहीं होगा, या जिसमें एक कमिट जैसी विशेषताएं होंगी जो सफल होंगी, या वापस वापस आ जाएगी। इसकी मूल स्थिति)।

C ++ की "छिपी" सुविधा का सबसे प्रसिद्ध टेम्पलेट मेटाप्रोग्रामिंग है , क्योंकि यह आपको रनटाइम के बजाय अपने प्रोग्राम को आंशिक रूप से (या पूरी तरह से) निष्पादित करने में सक्षम बनाता है। यह मुश्किल है, हालांकि, और आपको इसे आज़माने से पहले टेम्प्लेट पर एक ठोस समझ होनी चाहिए।

अन्य C ++ के पूर्वज, यानी C के बाहर "प्रोग्रामिंग के तरीके" के निर्माण के लिए कई प्रतिमानों का उपयोग करते हैं।

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

टेम्प्लेट का उपयोग करके , आप उस कोड का उत्पादन कर सकते हैं जो कि सबसे प्रकार पर काम करेगा, जिसमें वह नहीं है जिसे आपने पहले सोचा था। आप टाइप सुरक्षा बढ़ा सकते हैं, भी (जैसे एक स्वचालित टाइपसेक मॉलोक / रियललोक / फ्री)। C ++ ऑब्जेक्ट विशेषताएँ वास्तव में शक्तिशाली हैं (और इस प्रकार, खतरनाक अगर लापरवाही से उपयोग की जाती है), लेकिन यहां तक ​​कि गतिशील बहुरूपता का C ++ में इसका स्थिर संस्करण है: CRTP

मैंने पाया है कि स्कॉट मेयर्स की अधिकांश " प्रभावी C ++ " -प्रस्तुत पुस्तकें या " हर्ब सटर की असाधारण C ++ " -प्रकार की पुस्तकें दोनों को पढ़ना आसान है, और C ++ की ज्ञात और कम ज्ञात विशेषताओं पर जानकारी का काफी खजाना है।

मेरी पसंद में से एक है जो किसी भी जावा प्रोग्रामर के बालों को हॉरर से उभारना चाहिए: सी ++ में, एक ऑब्जेक्ट में एक फीचर जोड़ने का सबसे ऑब्जेक्ट-ओरिएंटेड तरीका एक सदस्य के बजाय गैर-सदस्य गैर-मित्र फ़ंक्शन के माध्यम से है। फ़ंक्शन (अर्थात कक्षा विधि), क्योंकि:

  • C ++ में, एक वर्ग का इंटरफ़ेस इसके सदस्य-फ़ंक्शन और समान नामस्थान में गैर-सदस्य फ़ंक्शन दोनों है

  • गैर-मित्र गैर-सदस्य कार्यों का वर्ग आंतरिक तक कोई विशेषाधिकार प्राप्त नहीं है। जैसे, एक गैर-सदस्य गैर-दोस्त से अधिक सदस्य फ़ंक्शन का उपयोग करने से कक्षा का इनकैप्सुलेशन कमजोर हो जाएगा।

यह कभी भी अनुभवी डेवलपर्स को आश्चर्यचकित करने में विफल नहीं होता है।

(स्रोत: दूसरों के बीच, हर्ब सटर के ऑनलाइन गुरु # द वीक # 84: http://www.gotw.ca/gotw/084.htm )


+1 बहुत गहन उत्तर। यह स्पष्ट कारणों के लिए अधूरा है (अन्यथा अब "छिपी हुई विशेषताएं" नहीं होंगी!): उत्तर के अंत में पहले बिंदु पर पी, आपने एक वर्ग इंटरफ़ेस के सदस्यों का उल्लेख किया। क्या आपका मतलब ".. इसके सदस्य-कार्य और मित्र गैर-सदस्य कार्य दोनों हैं"?
विल्हेमटेल


क्या आप 1 के साथ के बारे में उल्लेख कर रहे हैं koenig लुकअप होना चाहिए, है ना?
0zgür

1
@wilhelmtell: नो नो नो ... :- पी ... मेरा मतलब है "इसके सदस्य-फ़ंक्शंस और गैर-फ्रेंड गैर-सदस्य फ़ंक्शंस" .... कोएनिग का लुकअप यह सुनिश्चित करेगा कि इन कार्यों को अन्य की तुलना में जल्द ही माना जाएगा " बाहर "प्रतीकों के लिए अपनी खोज में काम करता है
पैरेसबल

7
महान पोस्ट, और +1 विशेष रूप से अंतिम भाग के लिए, जिसे बहुत कम लोग महसूस करते हैं। मैं शायद बूस्ट लाइब्रेरी को एक "हिडन फीचर" के रूप में भी जोड़ूंगा। मैं बहुत ज्यादा इसे मानक पुस्तकालय मानता हूं जो C ++ को होना चाहिए था। ;)
jalf

118

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

namespace fs = boost::filesystem;

fs::path myPath( strPath, fs::native );

1
यदि आप उपयोग नहीं करना चाहते हैं तो मुझे लगता है कि यह उपयोगी है using
सिकाई लिन

4
यह कार्यान्वयन के बीच स्विच करने के तरीके के रूप में भी उपयोगी है, चाहे वह थ्रेड-सेफ बनाम नॉन-थ्रेड-सेफ, या संस्करण 1 बनाम 2 का चयन करें
टोनी डेलरो

3
यह विशेष रूप से उपयोगी है यदि आप बड़े नेमस्पेस पदानुक्रम के साथ एक बहुत बड़ी परियोजना पर काम कर रहे हैं और आप अपने हेडर को नाम स्थान प्रदूषण का कारण नहीं बनाना चाहते हैं (और आप चाहते हैं कि आपकी चर घोषणाएं मानव-पठनीय हों)।
ब्रैंडन बोहर

102

न केवल एक forलूप के इनिट भाग में चर घोषित किए जा सकते हैं , बल्कि कक्षाएं और फ़ंक्शन भी।

for(struct { int a; float b; } loop = { 1, 2 }; ...; ...) {
    ...
}

यह विभिन्न प्रकारों के कई चर के लिए अनुमति देता है।


31
यह जानकर अच्छा लगा कि आप ऐसा कर सकते हैं, लेकिन व्यक्तिगत रूप से मैं वास्तव में ऐसा कुछ भी करने से बचने की कोशिश करूंगा। ज्यादातर क्योंकि यह पढ़ना मुश्किल है।
जूमलेटर जूल

2
वास्तव में, इस संदर्भ में क्या काम करेगा एक जोड़ी का उपयोग कर रहा है: के लिए (std :: pair <int, float> loop = std :: make_pair (1,2); loop.first> 0; loop.second + = 1)
वैलेंटाइन; Heinitz

2
@ वेलेंटिन अच्छी तरह से तो मैं आपको छुपी हुई सुविधा को डाउनवोट करने के बजाय VS2008 के खिलाफ एक बग्रेपोर्ट बनाने की कोशिश करने की सलाह देता हूं। यह स्पष्ट रूप से आपके संकलक का दोष है।
जोहान्स शाउब -

2
हम्म, यह msvc10 में भी काम नहीं करता है। कितना दुख :(
अवकाकर

2
@ वकार वास्तव में, gcc ने एक बग की शुरुआत की, जो इसे अस्वीकार कर देता है, v4.6 में :) gcc.gnu.org/bugzilla/show_bug.cgi?id=46791
जोहान्स

77

सरणी ऑपरेटर सहयोगी है।

A [8] * (A + 8) का पर्याय है। चूंकि जोड़ सहयोगी है, इसलिए इसे * (8 + ए) के रूप में फिर से लिखा जा सकता है, जो ..... 8 [ए] का पर्याय है।

आपने उपयोगी नहीं कहा ... :-)


15
दरअसल, इस ट्रिक का उपयोग करते समय, आपको वास्तव में ध्यान देना चाहिए कि आप किस प्रकार का उपयोग कर रहे हैं। A [8] वास्तव में 8 वीं A है जबकि 8 [A] पता पर शुरू होने वाला Ath पूर्णांक है। यदि A एक बाइट है, तो आपके पास एक बग है।
विंसेंट रॉबर्ट

38
आपका मतलब है "कम्यूटेटिव" जहां आप "साहचर्य" कहते हैं?
डेरेनव सेप

28
विन्सेंट, तुम गलत हो। इस प्रकार का Aकोई फर्क नहीं पड़ता। उदाहरण के लिए, यदि Aकोई होता char*, तो कोड अभी भी मान्य होता।
कोनराड रुडोल्फ

11
खबरदार कि A एक पॉइंटर होना चाहिए, न कि एक क्लास ओवरलोडिंग ऑपरेटर []।
डेविड रॉड्रिग्ज -

15
विन्सेन्ट, इसमें एक अभिन्न प्रकार और एक सूचक प्रकार होना चाहिए, और न ही C और न ही C ++ परवाह करता है कि कौन पहले जाता है।
डेविड थॉर्नले

73

एक बात जो बहुत कम जानी जाती है वह यह है कि यूनियनें भी टेम्प्लेट हो सकती हैं:

template<typename From, typename To>
union union_cast {
    From from;
    To   to;

    union_cast(From from)
        :from(from) { }

    To getTo() const { return to; }
};

और उनके पास निर्माता और सदस्य कार्य भी हो सकते हैं। बस कुछ भी नहीं है कि विरासत (आभासी कार्यों सहित) के साथ क्या करना है।


दिलचस्प! तो, क्या आपको सभी सदस्यों को इनिशियलाइज़ करना चाहिए? क्या यह सामान्य संरचना के आदेश का पालन करता है, जिसका अर्थ है कि पिछले सदस्य को "पहले के सदस्यों" के शीर्ष पर आरंभीकृत किया जाएगा?
j_random_hacker

j_random_hacker ओह, यह बकवास है। अच्छी पकड़। मैंने इसे लिखा क्योंकि यह एक संरचना होगी। रुको मैं इसे ठीक कर दूंगा
जोहान्स स्काउब -

क्या यह अपरिभाषित व्यवहार नहीं करता है?
ग्रेग बेकन

7
@gbacon, हाँ यह करता है, तो अपरिभाषित व्यवहार आह्वान करता है Fromऔर Toस्थापित करने और उपयोग किया जाता है तदनुसार। इस तरह के संघ को परिभाषित व्यवहार के साथ इस्तेमाल किया जा सकता है (हालांकि Toअहस्ताक्षरित चार की एक सरणी या एक प्रारंभिक अनुक्रम साझा करने के साथ From)। यहां तक ​​कि अगर आप इसे अपरिभाषित तरीके से उपयोग करते हैं, तो भी यह निम्न-स्तर के काम के लिए उपयोगी हो सकता है। वैसे भी, यह संघ के खाके का सिर्फ एक उदाहरण है - टेम्पर्ड यूनियन के लिए अन्य उपयोग हो सकते हैं।
जोहान्स शाउब -

3
कंस्ट्रक्टर के साथ सावधानी बरतें। ध्यान दें कि आपको केवल पहले तत्व का निर्माण करना आवश्यक है, और यह केवल C ++ 0x में अनुमत है। वर्तमान मानक के अनुसार, आपको तुच्छ रूप से रचनात्मक प्रकारों से चिपके रहना होगा। और कोई विध्वंसक नहीं।
पोटाटोस्वाटर

72

C ++ एक मानक है, इसमें कोई छिपी हुई विशेषताएं नहीं होनी चाहिए ...

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


65

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

किसी एन्यूमरेशन को पूर्णांक में बदलना

+AnEnumeratorValue

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

एक चर से मूल्य प्राप्त करें

आपको एक वर्ग का उपयोग करना होगा जो वर्ग परिभाषा से बाहर एक इन-क्लास स्थिर इनिलाइज़र का उपयोग करता है, लेकिन कभी-कभी यह लिंक करने में विफल रहता है? ऑपरेटर अपने प्रकारों पर निर्भरता या निर्भरता बनाए बिना एक अस्थायी बनाने में मदद कर सकता है

struct Foo {
  static int const value = 42;
};

// This does something interesting...
template<typename T>
void f(T const&);

int main() {
  // fails to link - tries to get the address of "Foo::value"!
  f(Foo::value);

  // works - pass a temporary value
  f(+Foo::value);
}

एक सूचक के लिए एक सरणी क्षय

क्या आप एक फंक्शन में दो पॉइंटर्स पास करना चाहते हैं, लेकिन यह सिर्फ काम नहीं करेगा? ऑपरेटर मदद कर सकता है

// This does something interesting...
template<typename T>
void f(T const& a, T const& b);

int main() {
  int a[2];
  int b[3];
  f(a, b); // won't work! different values for "T"!
  f(+a, +b); // works! T is "int*" both time
}

61

कांस्टेबल संदर्भों से बंधे अस्थायी लोगों का जीवनकाल वह होता है जिसके बारे में बहुत कम लोग जानते हैं। या कम से कम यह C ++ ज्ञान का मेरा पसंदीदा टुकड़ा है जिसके बारे में ज्यादातर लोग नहीं जानते हैं।

const MyClass& x = MyClass(); // temporary exists as long as x is in scope

3
क्या आप विस्तार से समझा सकते हैं? जैसा कि आप बस चिढ़ा रहे हैं;)
जोसेफ गार्विन

8
स्कोपगार्ड ( ddj.com/cpp/184403758 ) एक बेहतरीन उदाहरण है जो इस सुविधा का लाभ उठाता है।
एमएसएन

2
मैं जोसेफ गार्विन के साथ हूं। कृपया हमें बताएं।
पीटर मोर्टेंसन

मैंने सिर्फ टिप्पणियों में किया। इसके अलावा, यह एक संदर्भ संदर्भ पैरामीटर का उपयोग करने का एक स्वाभाविक परिणाम है।
एमएसएन


52

एक अच्छी सुविधा जिसका उपयोग अक्सर नहीं किया जाता है वह है कार्य-व्यापी प्रयास-कैच ब्लॉक:

int Function()
try
{
   // do something here
   return 42;
}
catch(...)
{
   return -1;
}

मुख्य उपयोग अन्य अपवाद वर्ग और पुनर्खरीद के लिए अपवाद का अनुवाद करना होगा, या अपवादों और रिटर्न-आधारित त्रुटि कोड हैंडलिंग के बीच अनुवाद करना होगा।


मुझे नहीं लगता कि आप returnफंक्शन ट्रायल के कैच ब्लॉक से, केवल पुनर्खरीद कर सकते हैं।
कांस्टेंटिन

मैंने सिर्फ उपरोक्त संकलन करने की कोशिश की, और इसने कोई चेतावनी नहीं दी। मुझे लगता है कि उपरोक्त उदाहरण काम करता है।
विविडोस

7
वापसी केवल निर्माणकर्ताओं के लिए प्रतिबंधित है। एक कंस्ट्रक्टर की फ़ंक्शन कोशिश ब्लॉक और सदस्यों को शुरू करने में त्रुटियों को पकड़ लेगी (केवल एक मामला जहां एक फ़ंक्शन ब्लॉक ब्लॉक फ़ंक्शन के अंदर एक कोशिश करने की तुलना में कुछ अलग करता है); फिर से नहीं फेंकने से अपूर्ण वस्तु उत्पन्न होगी।
puetzk

हाँ। यह बहुत उपयोगी है। मैंने अपवादों को पकड़ने और HRESULTS को वापस करने के लिए मैक्रोज़ BEGIN_COM_METHOD और END_COM_METHOD लिखा, ताकि अपवाद COM इंटरफ़ेस लागू करने वाले वर्ग से बाहर लीक न हो। इसने अच्छा काम किया।
स्कॉट लैंगहम

3
जैसा कि @puetzk द्वारा बताया गया है, यह एक निर्माणकर्ता की प्रारंभिक सूची में किसी भी चीज द्वारा फेंके गए अपवादों को संभालने का एकमात्र तरीका है , जैसे कि बेस क्लास के कंस्ट्रक्टर या डेटा सदस्यों के।
anton.burger

44

identity/ idमेटाफंक्शन के बारे में बहुत से लोग जानते हैं , लेकिन गैर-टेम्पलेट मामलों के लिए इसके लिए एक अच्छा उपयोग है: घोषणाओं को आसानी से लिखना:

// void (*f)(); // same
id<void()>::type *f;

// void (*f(void(*p)()))(int); // same
id<void(int)>::type *f(id<void()>::type *p);

// int (*p)[2] = new int[10][2]; // same
id<int[2]>::type *p = new int[10][2];

// void (C::*p)(int) = 0; // same
id<void(int)>::type C::*p = 0;

यह C ++ घोषणाओं को डिक्रिप्ट करने में बहुत मदद करता है!

// boost::identity is pretty much the same
template<typename T> 
struct id { typedef T type; };

दिलचस्प है, लेकिन शुरू में मुझे वास्तव में उन कुछ परिभाषाओं को पढ़ने में अधिक परेशानी हुई। सी ++ घोषणाओं के साथ अंदर से बाहर समस्या को ठीक करने का एक और तरीका कुछ टेम्पलेट प्रकार उपनाम लिखने के लिए है: template<typename Ret,typename... Args> using function = Ret (Args...); template<typename T> using pointer = *T;-> pointer<function<void,int>> f(pointer<function<void,void>>);या pointer<void(int)> f(pointer<void()>);याfunction<pointer<function<void,int>>,pointer<function<void,void>>> f;
bames53

42

एक बहुत ही छिपी हुई विशेषता यह है कि आप एक if कंडीशन में वेरिएबल्स को परिभाषित कर सकते हैं, और इसका दायरा केवल if और उसके अन्य ब्लॉक्स पर होगा:

if(int * p = getPointer()) {
    // do something
}

कुछ मैक्रोज़ इसका उपयोग करते हैं, उदाहरण के लिए इस तरह से कुछ "लॉक" स्कोप प्रदान करने के लिए:

struct MutexLocker { 
    MutexLocker(Mutex&);
    ~MutexLocker(); 
    operator bool() const { return false; } 
private:
    Mutex &m;
};

#define locked(mutex) if(MutexLocker const& lock = MutexLocker(mutex)) {} else 

void someCriticalPath() {
    locked(myLocker) { /* ... */ }
}

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

switch(int value = getIt()) {
    // ...
}

और थोड़ी देर में:

while(SomeThing t = getSomeThing()) {
    // ...
}

(और यह भी एक शर्त के लिए)। लेकिन मुझे यकीन नहीं है कि क्या ये सब उपयोगी हैं :)


साफ! मुझे कभी नहीं पता था कि आप ऐसा कर सकते हैं ... त्रुटि रिटर्न मूल्यों के साथ कोड लिखते समय यह (और होगा) कुछ परेशानी को बचाएगा। क्या इस रूप में अभी भी सशर्त का कोई रास्ता नहीं है! = 0 इस रूप में? अगर ((r r = func ()) <0) काम नहीं करता है ...
puetzk

puetzk, नहीं वहाँ नहीं है। लेकिन खुशी है कि आप इसे पसंद करते हैं :)
जोहान्स स्काउब -

4
@ फ़्रीच, यह C कोड में बिल्कुल भी संभव नहीं है। मुझे लगता है कि आप सोच रहे हैं if((a = f()) == b) ..., लेकिन यह जवाब वास्तव में स्थिति में परिवर्तनशील घोषित करता है।
जोहान्स शाउब -

1
@ यह बहुत अलग है, क्योंकि चर घोषणा को सीधे इसके बूलियन मान के लिए परीक्षण किया जाता है। फॉर-लूप्स के लिए भी एक मैपिंग है, जो ऐसा दिखता है कि for(...; int i = foo(); ) ...;यह शरीर के माध्यम से जाएगा जब तक कि iयह सही न हो, इसे फिर से शुरू करते हुए। लूप जो आप दिखाते हैं वह केवल एक चर घोषणा का प्रदर्शन कर रहा है, लेकिन एक चर घोषणा नहीं है जो एक साथ एक शर्त के रूप में कार्य करता है :)
जोहान्स स्काउब -

5
बहुत अच्छा है, सिवाय इसके कि आपने इस सुविधा के लिए उपयोग किए गए गतिशील सूचक नक्षत्रों का उल्लेख नहीं किया है, मुझे विश्वास है।
mmocny

29

कॉलिंग ऑपरेटर ओवरलोड से कॉमा ऑपरेटर को रोकना

कभी-कभी आप अल्पविराम ऑपरेटर का वैध उपयोग करते हैं, लेकिन आप यह सुनिश्चित करना चाहते हैं कि कोई भी उपयोगकर्ता परिभाषित अल्पविराम ऑपरेटर रास्ते में न आए, क्योंकि उदाहरण के लिए आप बाईं और दाईं ओर के बीच अनुक्रम बिंदुओं पर भरोसा करते हैं या यह सुनिश्चित करना चाहते हैं कि वांछित के साथ कुछ भी हस्तक्षेप न करें। कार्रवाई। यह वह जगह है जहाँ void()खेल में आता है:

for(T i, j; can_continue(i, j); ++i, void(), ++j)
  do_code(i, j);

मेरे द्वारा शर्त और कोड के लिए लगाए गए स्थान धारकों की उपेक्षा करें। क्या महत्वपूर्ण है void(), जो कंपाइलर को बिलिन कॉमा ऑपरेटर का उपयोग करने के लिए मजबूर करता है। यह गुण वर्गों को लागू करते समय उपयोगी हो सकता है, कभी-कभी, भी।


मैंने अभी-अभी अपना ओवरकिल एक्सप्रेशन इग्नोर खत्म करने के लिए इसका इस्तेमाल किया था । :)
GManNickG

28

कंस्ट्रक्टर में ऐरे इनिशियलाइज़ेशन। एक वर्ग में उदाहरण के लिए यदि हमारे पास एक सरणी है int:

class clName
{
  clName();
  int a[10];
};

हम सरणी में सभी तत्वों को अपने डिफ़ॉल्ट में (यहां सरणी के सभी तत्व शून्य में) को आरंभीकृत कर सकते हैं:

clName::clName() : a()
{
}

6
आप इसे किसी भी ऐरे से कहीं भी कर सकते हैं।
पोटाटोस्वाटर

@Potatoswatter: सबसे अधिक डरावने पार्स के कारण यह दिखने में कठिन है। मैं कहीं और के बारे में सोच भी नहीं सकता, शायद एक वापसी मूल्य को छोड़कर
Mooing Duck

यदि सरणी का प्रकार एक वर्ग प्रकार है, तो यह सही नहीं है?
थॉमस ईडिंग

27

ऊओह, मैं इसके बजाय पालतू जानवरों की सूची के साथ आ सकता हूं:

  • यदि आपको बहुरूपिक रूप से उपयोग करने का इरादा है, तो विध्वंसक को आभासी होना चाहिए
  • कभी-कभी सदस्य डिफ़ॉल्ट रूप से आरंभिक होते हैं, कभी-कभी वे नहीं होते हैं
  • स्थानीय मामलों का उपयोग टेम्पलेट मापदंडों के रूप में नहीं किया जा सकता है (उन्हें कम उपयोगी बनाता है)
  • अपवाद विनिर्देशक: उपयोगी दिखते हैं, लेकिन नहीं हैं
  • फ़ंक्शन अधिभार विभिन्न हस्ताक्षर के साथ बेस क्लास फ़ंक्शंस छिपाते हैं।
  • अंतर्राष्ट्रीयकरण पर कोई उपयोगी मानकीकरण (पोर्टेबल मानक विस्तृत चारसेट, कोई भी? हमें C ++ 0x तक इंतजार करना होगा)

सकारात्मक स्थिति की ओर

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

16
पालतू से घृणा: C ++ ऐप्स के लिए कोई परिभाषित ABI नहीं, C के विपरीत जिसका उपयोग हर कोई करता है क्योंकि हर भाषा C फ़ंक्शन को कॉल करने की गारंटी दे सकती है, कोई भी C ++ के लिए ऐसा नहीं कर सकता है।
gbjbaanb

8
विध्वंसक को केवल तभी आभासी होने की आवश्यकता है जब आप बहुरूपिए को नष्ट करने का इरादा रखते हैं, जो पहले बिंदु से थोड़ा अलग है।
डेविड रॉड्रिग्ज - dribeas

2
C ++ 0x के साथ स्थानीय प्रकारों को टेम्पलेट पैरामीटर के रूप में उपयोग किया जा सकता है।
तंस्नर

1
C ++ 0x के साथ, डिस्ट्रक्टर्स वर्चुअल होंगे यदि ऑब्जेक्ट में कोई वर्चुअल फ़ंक्शंस (यानी एक विटेबल) है।
मैके

NRVO को मत भूलना, और निश्चित रूप से किसी भी अनुकूलन को अनुमति दी जाती है जब तक कि यह प्रोग्राम आउटपुट को नहीं बदलता है
jk।

26

आप अनिर्धारित व्यवहार के बिना, और अपेक्षित शब्दार्थ के साथ किसी भी वर्ग के संरक्षित डेटा और फ़ंक्शन सदस्यों तक पहुँच सकते हैं। आगे पढ़िए कैसे। इसके बारे में दोष रिपोर्ट भी पढ़ें ।

आम तौर पर, C ++ आपको किसी वर्ग के ऑब्जेक्ट के गैर-स्थिर संरक्षित सदस्यों तक पहुंचने से मना करता है, भले ही वह वर्ग आपकी आधार श्रेणी हो

struct A {
protected:
    int a;
};

struct B : A {
    // error: can't access protected member
    static int get(A &x) { return x.a; }
};

struct C : A { };

यह निषिद्ध है: आप और संकलक यह नहीं जानते कि संदर्भ वास्तव में किस बिंदु पर है। यह एक Cवस्तु हो सकती है , जिस स्थिति में क्लास के Bपास अपने डेटा के बारे में कोई व्यवसाय और सुराग नहीं है। इस तरह की पहुंच केवल तभी दी जाती है जब xवह किसी व्युत्पन्न वर्ग का संदर्भ हो या उससे प्राप्त किया गया हो। और यह किसी भी संरक्षित सदस्य को केवल "फेंक-दूर" वर्ग बनाकर पढ़ने की अनुमति दे सकता है, जो उदाहरण के लिए सदस्यों को पढ़ता है std::stack:

void f(std::stack<int> &s) {
    // now, let's decide to mess with that stack!
    struct pillager : std::stack<int> {
        static std::deque<int> &get(std::stack<int> &s) {
            // error: stack<int>::c is protected
            return s.c;
        }
    };

    // haha, now let's inspect the stack's middle elements!
    std::deque<int> &d = pillager::get(s);
}

निश्चित रूप से, जैसा कि आप देखते हैं कि इससे बहुत अधिक नुकसान होगा। लेकिन अब, सदस्य संकेत इस सुरक्षा को दरकिनार करने की अनुमति देते हैं! मुख्य बिंदु यह है कि सदस्य पॉइंटर का प्रकार उस वर्ग से जुड़ा होता है जिसमें वास्तव में उक्त सदस्य होता है - उस वर्ग के लिए नहीं जो आपने पता लेते समय निर्दिष्ट किया था। यह हमें जाँच को दरकिनार करने की अनुमति देता है

struct A {
protected:
    int a;
};

struct B : A {
    // valid: *can* access protected member
    static int get(A &x) { return x.*(&B::a); }
};

struct C : A { };

और हां, यह std::stackउदाहरण के साथ भी काम करता है ।

void f(std::stack<int> &s) {
    // now, let's decide to mess with that stack!
    struct pillager : std::stack<int> {
        static std::deque<int> &get(std::stack<int> &s) {
            return s.*(pillager::c);
        }
    };

    // haha, now let's inspect the stack's middle elements!
    std::deque<int> &d = pillager::get(s);
}

व्युत्पन्न वर्ग में एक प्रयोग घोषणा के साथ यह और भी आसान होने जा रहा है, जो सदस्य के नाम को सार्वजनिक करता है और आधार वर्ग के सदस्य को संदर्भित करता है।

void f(std::stack<int> &s) {
    // now, let's decide to mess with that stack!
    struct pillager : std::stack<int> {
        using std::stack<int>::c;
    };

    // haha, now let's inspect the stack's middle elements!
    std::deque<int> &d = s.*(&pillager::c);
}


26

एक और छिपी विशेषता यह है कि आप क्लास ऑब्जेक्ट्स को कॉल कर सकते हैं जिन्हें फ़ंक्शन पॉइंटर्स या संदर्भों में परिवर्तित किया जा सकता है। उनके परिणाम के आधार पर अधिभार संकल्प किया जाता है, और तर्क पूरी तरह से अग्रेषित किए जाते हैं।

template<typename Func1, typename Func2>
class callable {
  Func1 *m_f1;
  Func2 *m_f2;

public:
  callable(Func1 *f1, Func2 *f2):m_f1(f1), m_f2(f2) { }
  operator Func1*() { return m_f1; }
  operator Func2*() { return m_f2; }
};

void foo(int i) { std::cout << "foo: " << i << std::endl; }
void bar(long il) { std::cout << "bar: " << il << std::endl; }

int main() {
  callable<void(int), void(long)> c(foo, bar);
  c(42); // calls foo
  c(42L); // calls bar
}

इन्हें "सरोगेट कॉल फ़ंक्शन" कहा जाता है।


1
जब आप कहते हैं कि ओवरलोड रिज़ॉल्यूशन उनके परिणाम के आधार पर किया जाता है, तो क्या इसका मतलब यह है कि यह वास्तव में इसे दोनों फ़नवेयर्स में कनवर्ट करता है और फिर ओवरलोड रिज़ॉल्यूशन करता है? मैंने ऑपरेटर Func1 * (), और ऑपरेटर Func2 * () में कुछ छापने की कोशिश की, लेकिन यह सही है कि जब यह पता चले कि रूपांतरण ऑपरेटर किसको आमंत्रित करेगा।
नेविगेटर

3
@navigator, yep यह वैचारिक रूप से दोनों में परिवर्तित हो जाता है और फिर सबसे अच्छा चुनता है। इसे वास्तव में उन्हें कॉल करने की आवश्यकता नहीं है, क्योंकि यह परिणाम-प्रकार से जानता है कि वे पहले से ही क्या उपज देंगे। वास्तविक कॉल तब किया जाता है जब यह पता चलता है कि आखिर क्या चुना गया था।
जोहान्स स्काउब -

26

छिपी विशेषताएं:

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

  3. समारोह की कोशिश ब्लॉक

  4. कक्षा के खाके में टाइप किए जाने वाले टंकणों को नष्ट करने का खाका। एक सदस्य टेम्पलेट विशेषज्ञता के नाम एक के बाद दिखाई देता है ., ->या ::ऑपरेटर, और कहा कि नाम स्पष्ट रूप से योग्य टेम्प्लेट पैरामीटर, कीवर्ड टेम्पलेट के साथ उपसर्ग सदस्य टेम्पलेट नाम है। और अधिक पढ़ें यहाँ

  5. फ़ंक्शन पैरामीटर डिफॉल्ट को रनटाइम पर बदला जा सकता है। और अधिक पढ़ें यहाँ

  6. A[i] जितना अच्छा काम करता है i[A]

  7. एक वर्ग के अस्थायी उदाहरणों को संशोधित किया जा सकता है! एक गैर-कॉन्स्टेबल सदस्य फ़ंक्शन को अस्थायी ऑब्जेक्ट पर लागू किया जा सकता है। उदाहरण के लिए:

    struct Bar {
      void modify() {}
    }
    int main (void) {
      Bar().modify();   /* non-const function invoked on a temporary. */
    }

    और अधिक पढ़ें यहाँ

  8. यदि :टर्नरी ( ?:) ऑपरेटर अभिव्यक्ति में पहले और बाद में दो अलग-अलग प्रकार मौजूद हैं , तो परिणामी प्रकार का अभिव्यक्ति वह है जो दो में से सबसे सामान्य है। उदाहरण के लिए:

    void foo (int) {}
    void foo (double) {}
    struct X {
      X (double d = 0.0) {}
    };
    void foo (X) {} 
    
    int main(void) {
      int i = 1;
      foo(i ? 0 : 0.0); // calls foo(double)
      X x;
      foo(i ? 0.0 : x);  // calls foo(X)
    }

पी डैडी: ए [i] == * (ए + आई) == * (आई + ए) == मैं [ए]
एबेलेंकी

मुझे कम्यूटेशन मिलता है, इसका मतलब सिर्फ इतना है कि [] का अपना कोई शब्दिक मूल्य नहीं है और यह केवल मैक्रो-स्टाइल रिप्लेसमेंट के बराबर है जहाँ "x [y]" को "(* (x) + (y) से बदल दिया जाता है ))) "। मुझे उम्मीद नहीं थी। मुझे आश्चर्य है कि यह इस तरह से परिभाषित क्यों है।
पी डैडी


2
अपने पहले बिंदु के बारे में: एक विशेष मामला है जहां आपको शुद्ध आभासी फ़ंक्शन को लागू करना है: शुद्ध आभासी विध्वंसक।
फ्रेरिच राबे

24

map::operator[]यदि कुंजी गुम है तो प्रविष्टि बनाता है और डिफ़ॉल्ट रूप से निर्मित प्रविष्टि मान का संदर्भ देता है। तो आप लिख सकते हैं:

map<int, string> m;
string& s = m[42]; // no need for map::find()
if (s.empty()) { // assuming we never store empty values in m
  s.assign(...);
}
cout << s;

मुझे आश्चर्य है कि कितने C ++ प्रोग्रामर को यह पता नहीं है।


11
और इसके विपरीत छोर पर आप संचालक का उपयोग नहीं कर सकते [] एक
कास्ट

2
निक के लिए +1, लोग पागल हो सकते हैं यदि वे इसके बारे में नहीं जानते हैं .find()
लीराणूना

या " const map::operator[]त्रुटि संदेश उत्पन्न करता है"
बस किसी को 20

2
भाषा की एक विशेषता नहीं है, यह मानक टेम्पलेट लाइब्रेरी की एक विशेषता है। यह भी बहुत स्पष्ट है, क्योंकि ऑपरेटर [] एक वैध संदर्भ देता है।
रेमन ज़राज़ुआ बी।

2
मुझे कुछ समय के लिए C # में मैप्स का उपयोग करना था, जहां मैप्स उस तरह का व्यवहार नहीं करते हैं, ताकि यह महसूस हो सके कि यह एक विशेषता है। मुझे लगा कि जितना मैंने इसे इस्तेमाल किया है, उससे अधिक मैं इससे नाराज था, लेकिन ऐसा लगता है कि मैं गलत था। मैं इसे C # में मिस कर रहा हूं।
sbi

20

कार्यों या चरों को एक नाममात्र नामस्थान में रखने staticसे उन्हें फाइल स्कोप तक सीमित रखने का उपयोग होता है।


"पदावनत" एक मजबूत शब्द है ...
पोटाटोस्वाटर

@Potato: पुरानी टिप्पणी, मुझे पता है, लेकिन मानक का कहना है कि नेमस्पेस स्कोप में स्थैतिक का उपयोग बिना नाम के स्थान के लिए वरीयता के साथ किया जाता है।
GManNickG

@ मन: कोई संभावना नहीं, मुझे नहीं लगता कि वास्तव में एसओ पृष्ठ "मर जाते हैं।" कहानी के दोनों पक्षों के लिए, staticवैश्विक दायरे में किसी भी तरह से चित्रित नहीं किया गया है। (संदर्भ के लिए: C ++ 03 .2D.2)
Potatoswatter

आह, करीब से पढ़ने पर, "वैश्विक नामस्थान में घोषित एक नाम में वैश्विक नाम स्थान का स्कोप (जिसे वैश्विक स्कोप भी कहा जाता है)।" क्या इसका वास्तव में मतलब है?
पोटाटोस्वाटर

@ पाटो: युप। :) staticउपयोग केवल एक वर्ग-प्रकार या फ़ंक्शन के भीतर किया जाना चाहिए।
GMANNICKG

19

क्लास टेम्प्लेट में साधारण मित्र कार्यों को परिभाषित करने पर विशेष ध्यान देने की आवश्यकता है:

template <typename T> 
class Creator { 
    friend void appear() {  // a new function ::appear(), but it doesn't 
                           // exist until Creator is instantiated 
    } 
};
Creator<void> miracle;  // ::appear() is created at this point 
Creator<double> oops;   // ERROR: ::appear() is created a second time! 

इस उदाहरण में, दो अलग-अलग तात्कालिकताएं दो समान परिभाषाएं बनाती हैं - ओडीआर का सीधा उल्लंघन

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

template <typename T> 
class Creator { 
    friend void feed(Creator<T>*){  // every T generates a different 
                                   // function ::feed() 
    } 
}; 

Creator<void> one;     // generates ::feed(Creator<void>*) 
Creator<double> two;   // generates ::feed(Creator<double>*) 

डिस्क्लेमर: मैंने इस सेक्शन को C ++ टेम्प्लेट्स: कम्प्लीट गाइड / सेक्शन 8.4 से पेस्ट किया है


18

शून्य फ़ंक्शन शून्य मान लौटा सकते हैं

थोड़ा ज्ञात है, लेकिन निम्नलिखित कोड ठीक है

void f() { }
void g() { return f(); }

निम्नलिखित अजीब लग रही के रूप में अस्वेल

void f() { return (void)"i'm discarded"; }

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

template<typename T>
struct sample {
  // assume f<T> may return void
  T dosomething() { return f<T>(); }

  // better than T t = f<T>(); /* ... */ return t; !
};

17

तार के वेक्टर में एक फ़ाइल पढ़ें:

 vector<string> V;
 copy(istream_iterator<string>(cin), istream_iterator<string>(),
     back_inserter(V));

istream_iterator


8
या: वेक्टर <string> V ((istream_iterator <string> (cin)), istream_iterator <string>);
अंकलबीन्स

5
आप का मतलब है vector<string> V((istream_iterator<string>(cin)), istream_iterator<string>());- दूसरे परम के बाद लापता कोष्ठक
knittl

1
यह वास्तव में एक छिपी सी ++ सुविधा नहीं है। एसटीएल की अधिक सुविधा। STL! = A भाषा
निक बेडफोर्ड

14

आप बिटफिल्ड को टेम्प्लेट कर सकते हैं।

template <size_t X, size_t Y>
struct bitfield
{
    char left  : X;
    char right : Y;
};

मुझे अभी तक इसके लिए किसी भी उद्देश्य के साथ नहीं आना है, लेकिन यह निश्चित है कि बिल्ली ने मुझे आश्चर्यचकित किया है।


1
यहाँ देखें, जहाँ मैंने हाल ही में इसे n-bit अंकगणित के लिए सुझाया है: stackoverflow.com/questions/8309538/…
sehe

14

किसी भी प्रोग्रामिंग भाषाओं के सबसे दिलचस्प व्याकरणों में से एक।

इनमें से तीन चीजें एक साथ हैं, और दो पूरी तरह से अलग हैं ...

SomeType t = u;
SomeType t(u);
SomeType t();
SomeType t;
SomeType t(SomeType(u));

सभी लेकिन तीसरा और पांचवां SomeTypeस्टैक पर एक ऑब्जेक्ट को परिभाषित करते हैं और इसे इनिशियलाइज़ करते हैं ( uपहले दो केस के साथ, और चौथे में डिफ़ॉल्ट कंस्ट्रक्शन। तीसरा एक फ़ंक्शन घोषित कर रहा है जो कोई पैरामीटर नहीं लेता है और एक रिटर्न देता है SomeType। पांचवां भी इसी तरह की घोषणा कर रहा है। एक फ़ंक्शन जो SomeTypeनामित नाम के प्रकार से एक पैरामीटर लेता है u


क्या 1 और 2 के बीच कोई अंतर है? हालांकि, मुझे पता है कि वे दोनों आरंभीकरण हैं।
20zgür

Comptrol: मुझे ऐसा नहीं लगता। दोनों कॉपी-कंस्ट्रक्टर को कॉल करना समाप्त कर देंगे, भले ही असाइनमेंट ऑपरेटर की तरह पहले एक एलओकेएस, यह वास्तव में कॉपी-कंस्ट्रक्टर है।
अबेलेंकी

1
यदि SomeType से u एक अलग प्रकार है, तो पहले एक रूपांतरण निर्माता को पहले और फिर प्रतिलिपि निर्माता को कॉल करेगा, जबकि दूसरा केवल रूपांतरण निर्माता को कॉल करेगा।
ग्रहण

3
1 निर्माणकर्ता की निहित कॉल है, दूसरा स्पष्ट कॉल है। अंतर को देखने के लिए निम्नलिखित कोड देखें: #include <iostream> class sss {public: clear sss (int) {std :: cout << "int" << std :: endl; }; sss (डबल) {std :: cout << "double" << std :: endl; }; }; int main () {sss ddd (7); // कॉल इंट कंस्ट्रक्टर sss xxx = 7; // कॉल डबल कंस्ट्रक्टर रिटर्न 0; }
किरिल वी। लयाडविंस्की

सही - अगर कंस्ट्रक्टर स्पष्ट घोषित किया गया है तो पहली पंक्ति काम नहीं करेगी।
ग्रहण

12

आगे की घोषणाओं से छुटकारा:

struct global
{
     void main()
     {
           a = 1;
           b();
     }
     int a;
     void b(){}
}
singleton;

के साथ स्विच-स्टेटमेंट लिखना ;: ऑपरेटर:

string result = 
    a==0 ? "zero" :
    a==1 ? "one" :
    a==2 ? "two" :
    0;

सब कुछ एक ही लाइन पर करना:

void a();
int b();
float c = (a(),b(),1.0f);

मेमरी के बिना शून्य संरचनाएं:

FStruct s = {0};

सामान्यीकरण / रैपिंग कोण- और समय-मान:

int angle = (short)((+180+30)*65536/360) * 360/65536; //==-150

संदर्भ निर्दिष्ट करना:

struct ref
{
   int& r;
   ref(int& r):r(r){}
};
int b;
ref a(b);
int c;
*(int**)&a = &c;

2
FStruct s = {};और भी छोटा है।
कांस्टेंटिन

अंतिम उदाहरण में, यह सरल होगा: (ए); ख (); फ्लोट c = 1.0f;
ज़िफरे

2
यह वाक्यविन्यास "फ्लोट सी = (ए), बी (), 1.0 एफ);" उच्चारण-संचालन ("सी" के आत्मसात) उच्चारण के लिए उपयोगी है। प्रोग्रामिंग में एसिगमेंट-ऑपरेशंस महत्वपूर्ण हैं, क्योंकि वे कम होने वाले आईएमओ बनने की संभावना कम है। पता नहीं क्यों, कार्यात्मक प्रोग्रामिंग के साथ कुछ किया जा सकता है जहां कार्यक्रम राज्य को हर फ्रेम को फिर से सौंपा गया है। पुनश्च। और नहीं, "int d = (11,22,1.0f)" "1" के बराबर होगा। VS2008 के साथ एक मिनट पहले परीक्षण किया गया।
आरेप

2
+1 क्या आपको फोन नहीं करना चाहिए main? मैं सुझाव देता हूं global().main();और केवल सिंगलटन के बारे में भूल जाओ ( आप केवल अस्थायी के साथ काम कर सकते हैं, जो इसे जीवनकाल विस्तारित हो जाता है )
sehe

1
मुझे संदेह है कि संदर्भ निर्दिष्ट करना पोर्टेबल है। हालांकि मुझे आगे की घोषणाओं को माफ करने के लिए संरचना पसंद है।
थॉमस ईडिंग

12

टर्नरी सशर्त ऑपरेटर ?:को अपने दूसरे और तीसरे ऑपरेंड के लिए "सहमत" प्रकार (अनौपचारिक रूप से बोलना) की आवश्यकता होती है। लेकिन इस आवश्यकता का एक अपवाद (वाक्य का उद्देश्य) है: या तो दूसरा या तीसरा ऑपरेंड एक फेंक अभिव्यक्ति हो सकता है (जिसमें प्रकार हैvoid ), भले ही अन्य ऑपरेंड के प्रकार की परवाह किए बिना।

दूसरे शब्दों में, कोई ?:ऑपरेटर का उपयोग करके निम्नलिखित सही ढंग से मान्य C ++ अभिव्यक्ति लिख सकता है

i = a > b ? a : throw something();

BTW, यह तथ्य कि अभिव्यक्ति को फेंकना वास्तव में एक अभिव्यक्ति (प्रकार का void) है और न कि एक कथन C ++ भाषा की एक और अल्प-ज्ञात विशेषता है। इसका मतलब है, अन्य बातों के अलावा, कि निम्नलिखित कोड पूरी तरह से मान्य है

void foo()
{
  return throw something();
}

हालाँकि इसे इस तरह करने का कोई मतलब नहीं है (हो सकता है कि कुछ सामान्य टेम्पलेट कोड में यह काम आए)।


इसके लायक क्या है, इस पर नील का सवाल है: stackoverflow.com/questions/1212978/… , अतिरिक्त जानकारी के लिए।
GManNickG

12

प्रभुत्व नियम उपयोगी है, लेकिन बहुत कम ज्ञात है। यह कहता है कि भले ही एक बेस-क्लास जाली के माध्यम से एक गैर-अद्वितीय पथ में, आंशिक रूप से छिपे हुए सदस्य के लिए नाम-लुकअप अद्वितीय है यदि सदस्य वर्चुअल बेस-क्लास से संबंधित है:

struct A { void f() { } };

struct B : virtual A { void f() { cout << "B!"; } };
struct C : virtual A { };

// name-lookup sees B::f and A::f, but B::f dominates over A::f !
struct D : B, C { void g() { f(); } };

मैंने इसका उपयोग संरेखण-समर्थन को लागू करने के लिए किया है जो कि प्रभुत्व शासन के माध्यम से स्वचालित रूप से सबसे सख्त संरेखण का पता लगाता है।

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


1
साफ। struct Cआपके उदाहरण में शामिल कोई विशेष कारण ...? चीयर्स।
टोनी डेलरो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.