परिचय
C++ एक शक्तिशाली और लचीली प्रोग्रामिंग भाषा है जो डेवलपर को सिस्टम संसाधनों पर अत्यधिक नियंत्रण प्रदान करती है। हालाँकि, यह स्वतंत्रता बड़ी जिम्मेदारी के साथ आती है। शुरुआती प्रोग्रामर अक्सर ऐसी गलतियाँ करते हैं जो बग, मेमोरी लीक और अपरिभाषित व्यवहार का कारण बन सकती हैं, जिन्हें ढूंढना मुश्किल होता है। इस लेख में, हम शुरुआती C++ डेवलपर्स की शीर्ष गलतियाँ देखेंगे और दिखाएंगे कि उनसे कैसे बचा जाए।
1. मेमोरी लीक और गलत संसाधन प्रबंधन
समस्या: new/delete के माध्यम से मैन्युअल मेमोरी प्रबंधन
सबसे आम गलतियों में से एक है new के माध्यम से बनाई गई वस्तु के लिए delete कॉल करना भूल जाना। इससे मेमोरी लीक होती है।
void example() { int* ptr = new int(42); // ... कुछ कोड ... // delete ptr भूल गए;}अधिक जटिल मामलों में, यदि new और delete के बीच कोई अपवाद आता है, तो मेमोरी भी मुक्त नहीं होती है।
समाधान: RAII और स्मार्ट पॉइंटर्स का उपयोग करें
C++11 और नए मानक स्मार्ट पॉइंटर्स प्रदान करते हैं जो स्वचालित रूप से किसी वस्तु के जीवनकाल का प्रबंधन करते हैं।
#include <memory>
void example() { std::unique_ptr<int> ptr = std::make_unique<int>(42); // स्कोप छोड़ने पर मेमोरी स्वचालित रूप से मुक्त हो जाएगी}सरणियों के लिए, मैन्युअल प्रबंधन के बजाय std::vector का उपयोग करें:
// बुरा:int* arr = new int[100];// ... काम ...delete[] arr;
// अच्छा:std::vector<int> arr(100);// मेमोरी स्वचालित रूप से प्रबंधित होती है2. अपरिभाषित व्यवहार
समस्या: सरणी सूचकांक सीमा से बाहर
C++ में कच्ची सरणियों के लिए कोई अंतर्निहित सीमा जाँच नहीं है। सरणी के बाहर किसी तत्व तक पहुँचना क्लासिक अपरिभाषित व्यवहार है।
int arr[5] = {1, 2, 3, 4, 5};arr[10] = 42; // अपरिभाषित व्यवहार! शायद काम करे, शायद क्रैश होसमाधान: at() के साथ std::array और std::vector का उपयोग करें
#include <vector>#include <array>
std::array<int, 5> arr = {1, 2, 3, 4, 5};// arr.at(10) std::out_of_range अपवाद फेंकेगा
std::vector<int> vec = {1, 2, 3};vec.at(5); // सुरक्षित सीमा जाँचसमस्या: अप्रारंभीकृत चर का उपयोग
int x;std::cout << x; // अपरिभाषित व्यवहार: x प्रारंभीकृत नहीं हैहमेशा चर को प्रारंभीकृत करें:
int x = 0;int* ptr = nullptr;3. पॉइंटर्स और रेफरेंसेज के बीच भ्रम
समस्या: स्थानीय वस्तु का पॉइंटर लौटाना
int* getBadPointer() { int local = 42; return &local; // त्रुटि! फ़ंक्शन से बाहर निकलने पर local नष्ट हो जाता है}इससे डैंगलिंग पॉइंटर होता है। ऐसे पॉइंटर का उपयोग करना अपरिभाषित व्यवहार है।
समाधान: मान द्वारा लौटाएँ या स्मार्ट पॉइंटर्स का उपयोग करें
// मान द्वारा लौटाएँ (सरल प्रकारों के लिए पसंदीदा)int getValue() { return 42;}
// डायनामिक वस्तुओं के लिए स्मार्ट पॉइंटर लौटाएँstd::unique_ptr<MyClass> createObject() { return std::make_unique<MyClass>();}समस्या: रेफरेंसेज और पॉइंटर्स के बीच भ्रम
रेफरेंसेज nullptr नहीं हो सकते और उन्हें पुन: असाइन नहीं किया जा सकता। पॉइंटर्स हो सकते हैं। शुरुआती अक्सर रेफरेंस की अपेक्षा करने वाले फ़ंक्शन में nullptr पास करने की कोशिश करते हैं।
void process(int& ref) { // ref एक मौजूदा वस्तु को संदर्भित करने की गारंटी है}
int* ptr = nullptr;// process(*ptr); // त्रुटि! nullptr को डीरेफरेंस करना UB हैजब वस्तु आवश्यक हो तो रेफरेंसेज का उपयोग करें, और जब null हो सकता है तो पॉइंटर्स (या std::optional) का उपयोग करें।