C++ में अंडरस्कोर: गैर-स्पष्ट नियम जो कोड को तोड़ते हैं

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

C++ में अंडरस्कोर: आपके कोड के मूक हत्यारे

\n\n

एक स्थिति की कल्पना करें: आप साफ, सुंदर C++ कोड लिख रहे हैं। कंपाइलर चुप है, लिंटर शिकायत नहीं करता, सब कुछ पूरी तरह से काम करता है। और फिर — बैम! — और किसी दूसरे कंपाइलर पर या मानक के नए संस्करण के साथ, बिना किसी स्पष्ट कारण के सब कुछ टूट जाता है। परिचित लगता है?

\n\n

अक्सर बुराई की जड़ प्रतीत होने वाले हानिरहित अंडरस्कोर प्रतीकों (_) में छिपी होती है। यह विषय शुरुआती और यहां तक कि अनुभवी C++ डेवलपर्स के लिए एक वास्तविक "कब्रिस्तान" है। यह कोई आश्चर्य की बात नहीं है कि Stack Overflow पर अंडरस्कोर के उपयोग के नियमों के बारे में प्रश्न ने दसियों हज़ार बार देखा गया है। आइए एक बार और हमेशा के लिए समझ लें कि क्या किया जा सकता है, क्या नहीं, और अनिर्धारित व्यवहार (UB) के जाल में कैसे न फंसें।

\n\n

C++ मानक अंडरस्कोर के प्रति इतना सख्त क्यों है?

\n\n

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

\n\n

C++ मानक (C++03 से शुरू होकर और सभी बाद के संस्करणों में, जिसमें C++20 और C++23 शामिल हैं) स्पष्ट रूप से निर्दिष्ट करता है कि कौन से पहचानकर्ता कार्यान्वयन के लिए आरक्षित हैं। इन नियमों का उल्लंघन आपके कोड को न केवल गलत बनाता है, बल्कि अपोर्टेबल बनाता है।

\n\n

अंडरस्कोर के साथ शीर्ष 5 घातक त्रुटियाँ

\n\n

आइए सबसे आम गलतियों का विश्लेषण करें जिन पर अनुभवी प्रोग्रामर भी कदम रखते हैं।

\n\n

त्रुटि #1: कहीं भी डबल अंडरस्कोर

\n\n

नियम: कोई भी पहचानकर्ता जिसमें कहीं भी दो क्रमिक अंडरस्कोर वर्ण (__) हों, कार्यान्वयन के लिए आरक्षित है।

\n\n
// बुरा! "कार्यान्वयन" के लिए आरक्षित\nint __myVariable = 42;\nvoid my__function();\nclass My__Class {};\n\n// अच्छा\nint myVariable = 42;\nvoid my_function();\nclass MyClass {};\n
\n\n

यह खतरनाक क्यों है? कंपाइलर अपने आंतरिक मैक्रोज़ के लिए __myVariable का उपयोग कर सकता है। उदाहरण के लिए, कई कंपाइलर __LINE__ या __cplusplus को परिभाषित करते हैं। यदि आप अपना स्वयं का __LINE__ बनाते हैं, तो कंपाइलर आपकी परिभाषा को अनदेखा कर सकता है या, इससे भी बुरा, इसे अपने मान से बदल सकता है। परिणाम — UB।

\n\n

त्रुटि #2: वैश्विक क्षेत्र में अंडरस्कोर + बड़ा अक्षर

\n\n

नियम: एक पहचानकर्ता जो अंडरस्कोर से शुरू होता है और उसके बाद बड़ा अक्षर (A-Z) आता है, किसी भी दायरे में कार्यान्वयन के लिए आरक्षित है।

\n\n
// बुरा! स्थानीय दायरे में भी!\nvoid foo() {\n    int _MyVar = 10; // नियम का उल्लंघन\n}\n\n// बुरा! वैश्विक रूप से तो और भी अधिक\nint _GlobalVar = 20;\n\n// अच्छा\nvoid foo() {\n    int myVar = 10;\n}\n
\n\n

यह नियम सबसे कपटी है। बहुत से लोग सोचते हैं: "ठीक है, मैं फंक्शन के अंदर हूँ, इससे किसे कोई फर्क पड़ता है?" फर्क पड़ता है! मानक स्थानीय दायरे के लिए कोई अपवाद नहीं बनाता यदि पहचानकर्ता अंडरस्कोर और बड़े अक्षर से शुरू होता है। कंपाइलर को अपने उद्देश्यों के लिए ऐसे नाम आरक्षित करने का पूरा अधिकार है।

\n\n

त्रुटि #3: शुरुआत में अंडरस्कोर + वैश्विक क्षेत्र में छोटा अक्षर

\n\n

नियम: एक पहचानकर्ता जो अंडरस्कोर से शुरू होता है और उसके बाद छोटा अक्षर (a-z) आता है, वैश्विक दायरे (namespace scope) में कार्यान्वयन के लिए आरक्षित है।

\n\n
// बुरा! वैश्विक नाम स्थान में\nint _myGlobal = 0;\nvoid _helperFunction();\n\n// अच्छा — फंक्शन या क्लास के अंदर\nclass MyClass {\n    int _memberVar; // क्लास के अंदर — ठीक है (लेकिन m_ बेहतर है)\n};\n\nvoid foo() {\n    int _localVar = 5; // फंक्शन के अंदर                

ब्लॉग

पुस्तक अनुशंसाएँ