उत्तर आपके दृष्टिकोण पर निर्भर करता है:
यदि आप C ++ मानक से न्याय करते हैं, तो आपको अशक्त संदर्भ नहीं मिल सकता क्योंकि आपको पहले अपरिभाषित व्यवहार मिलता है। अपरिभाषित व्यवहार की पहली घटना के बाद, मानक कुछ भी होने की अनुमति देता है। इसलिए, यदि आप लिखते हैं *(int*)0
, तो आपके पास पहले से ही अपरिभाषित व्यवहार है जैसा कि आप भाषा मानक दृष्टिकोण से करते हैं, अशक्त सूचक को निष्क्रिय करते हैं। बाकी कार्यक्रम अप्रासंगिक है, एक बार जब इस अभिव्यक्ति को निष्पादित किया जाता है, तो आप खेल से बाहर हो जाते हैं।
हालांकि, व्यवहार में, अशक्त संदर्भों को आसानी से अशक्त बिंदुओं से बनाया जा सकता है, और जब तक आप वास्तव में अशक्त संदर्भ के पीछे मूल्य तक पहुंचने का प्रयास नहीं करते हैं, तब तक आप नोटिस नहीं करेंगे। आपका उदाहरण थोड़ा सरल हो सकता है, क्योंकि कोई भी अच्छा अनुकूलन करने वाला कंपाइलर अपरिभाषित व्यवहार को देखेगा, और बस उस पर निर्भर होने वाली किसी भी चीज का अनुकूलन करेगा (अशक्त संदर्भ भी नहीं बनाया जाएगा, यह अनुकूलित हो जाएगा)।
फिर भी, वह अनुकूलन दूर अपरिभाषित व्यवहार को साबित करने के लिए संकलक पर निर्भर करता है, जो करना संभव नहीं हो सकता है। एक फ़ाइल के अंदर इस सरल कार्य पर विचार करें converter.cpp
:
int& toReference(int* pointer) {
return *pointer;
}
जब कंपाइलर इस फ़ंक्शन को देखता है, तो यह नहीं जानता है कि सूचक एक अशक्त सूचक है या नहीं। तो यह सिर्फ एक कोड बनाता है जो किसी भी पॉइंटर को संबंधित संदर्भ में बदल देता है। (Btw: यह एक नोक है क्योंकि संकेत और संदर्भ कोडांतरक में एक ही जानवर हैं।) अब, यदि आपके पास user.cpp
कोड के साथ एक और फ़ाइल है
#include "converter.h"
void foo() {
int& nullRef = toReference(nullptr);
cout << nullRef; //crash happens here
}
संकलक को पता नहीं है कि toReference()
पारित किए गए सूचक को निष्क्रिय कर देगा, और मान लें कि यह एक वैध संदर्भ लौटाता है, जो व्यवहार में एक शून्य संदर्भ होगा। कॉल सफल होता है, लेकिन जब आप संदर्भ का उपयोग करने का प्रयास करते हैं, तो प्रोग्राम क्रैश हो जाता है। उम्मीद है कि। मानक कुछ भी होने की अनुमति देता है, जिसमें गुलाबी हाथियों की उपस्थिति भी शामिल है।
आप पूछ सकते हैं कि यह प्रासंगिक क्यों है, आखिरकार, अपरिभाषित व्यवहार पहले से ही अंदर ट्रिगर किया गया था toReference()
। उत्तर डिबगिंग है: अशक्त संदर्भों का प्रचार और प्रसार उसी तरह हो सकता है जैसे कि शून्य बिंदु करते हैं। यदि आप इस बात से अवगत नहीं हैं कि अशक्त संदर्भ मौजूद हो सकते हैं, और उन्हें बनाने से बचने के लिए सीख सकते हैं, तो आप यह जानने में काफी समय बिता सकते हैं कि आपका सदस्य फ़ंक्शन क्रैश क्यों हो रहा है जब वह एक सादे पुराने int
सदस्य को पढ़ने की कोशिश कर रहा है (उत्तर: उदाहरण सदस्य के आह्वान में एक शून्य संदर्भ था, इसलिए this
एक शून्य सूचक है, और आपके सदस्य की गणना 8 के रूप में होने के लिए गणना की जाती है)।
तो अशक्त संदर्भों के लिए जाँच कैसे की जाती है? आपने लाइन दी
if( & nullReference == 0 ) // null reference
आपके सवाल में। ठीक है, यह काम नहीं करेगा: मानक के अनुसार, यदि आपके पास अशक्त सूचक है, तो आपके पास अपरिभाषित व्यवहार है, और आप अशक्त संदर्भ को निष्क्रिय किए बिना एक शून्य संदर्भ नहीं बना सकते हैं, इसलिए अशक्त संदर्भ केवल अपरिभाषित व्यवहार के दायरे में मौजूद हैं। चूंकि आपका कंपाइलर यह मान सकता है कि आप अपरिभाषित व्यवहार को ट्रिगर नहीं कर रहे हैं, यह मान सकते हैं कि अशक्त संदर्भ जैसी कोई चीज नहीं है (भले ही यह आसानी से कोड का उत्सर्जन करेगा जो अशक्त संदर्भ उत्पन्न करता है!)। जैसे, यह if()
स्थिति को देखता है , निष्कर्ष निकालता है कि यह सच नहीं हो सकता है, और बस पूरे if()
बयान को दूर फेंक देना चाहिए । लिंक टाइम ऑप्टिमाइजेशन की शुरूआत के साथ, एक मजबूत तरीके से अशक्त संदर्भों की जांच करना सरल असंभव हो गया है।
टी एल; डॉ:
अशक्त संदर्भ कुछ हद तक अस्तित्व में हैं:
उनका अस्तित्व असंभव लगता है (= मानक द्वारा),
लेकिन वे मौजूद हैं (= उत्पन्न मशीन कोड द्वारा),
लेकिन आप उन्हें नहीं देख सकते हैं यदि वे मौजूद हैं (= आपके प्रयास दूर हो जाएंगे),
लेकिन वे आपको अनजान भी मार सकते हैं (= आपका कार्यक्रम अजीब बिंदुओं, या बदतर) पर क्रैश होता है।
आपकी एकमात्र आशा है कि वे मौजूद नहीं हैं (= उन्हें बनाने के लिए अपना कार्यक्रम न लिखें)।
मैं आशा करता हूं कि आपको परेशान नहीं करना पड़ेगा!