क्या वास्तव में nullptr है?


570

अब हमारे पास कई नई सुविधाओं के साथ C ++ 11 है। एक दिलचस्प और भ्रमित करने वाला (कम से कम मेरे लिए) नया हैnullptr

खैर, अब स्थूल मैक्रो के लिए कोई ज़रूरत नहीं है NULL

int* x = nullptr;
myclass* obj = nullptr;

फिर भी, मुझे नहीं मिल रहा है कि कैसे nullptrकाम करता है। उदाहरण के लिए, विकिपीडिया लेख कहता है:

C ++ 11 एक विशिष्ट नल पॉइंटर निरंतर: nullptr के रूप में सेवा करने के लिए एक नया कीवर्ड प्रस्तुत करके इसे सही करता है । यह टाइप nullptr_t का है , जो कि किसी भी पॉइंटर टाइप या पॉइंटर-टू-मेंबर टाइप के लिए समान रूप से कन्वर्टिबल और तुलनीय है। यह स्पष्ट रूप से परिवर्तनीय या अभिन्न प्रकारों के लिए तुलनीय नहीं है, बूल को छोड़कर।

यह एक कीवर्ड और एक प्रकार का उदाहरण कैसे है?

इसके अलावा, क्या आपके पास एक और उदाहरण है (विकिपीडिया के बगल में) जहां nullptrअच्छा पुराने से बेहतर है 0?


23
संबंधित तथ्य: nullptrC ++ / CLI में प्रबंधित हैंडल के लिए अशक्त संदर्भ को दर्शाने के लिए भी उपयोग किया जाता है।
मेहरदाद अफश्री

3
Visual C ++ का उपयोग करते समय, याद रखें कि यदि आप मूल C / C ++ कोड के साथ nullptr का उपयोग करते हैं और फिर / clr संकलक विकल्प के साथ संकलित करते हैं, तो संकलक यह निर्धारित नहीं कर सकता है कि nullptr एक देशी या प्रबंधित नल सूचक मान को इंगित करता है या नहीं। संकलक को अपना इरादा स्पष्ट करने के लिए, मूल मान निर्दिष्ट करने के लिए प्रबंधित मूल्य या __nullptr निर्दिष्ट करने के लिए nullptr का उपयोग करें। Microsoft ने इसे घटक विस्तार के रूप में लागू किया है।
crewer

6
क्या nullptr_tकेवल एक ही सदस्य होने की गारंटी है nullptr? इसलिए, यदि कोई फ़ंक्शन वापस आया है nullptr_t, तो संकलक को पहले से ही पता है कि फ़ंक्शन के निकाय की परवाह किए बिना, कौन सा मान लौटाया जाएगा?
एरोन मैकडैड

8
@AaronMcDaid std::nullptr_tको तत्काल किया जा सकता है, लेकिन सभी उदाहरण समान होंगे nullptrक्योंकि इस प्रकार को परिभाषित किया गया है typedef decltype(nullptr) nullptr_t। मेरा मानना ​​है कि प्राथमिक कारण इस प्रकार मौजूद है कि nullptrयदि आवश्यक हो तो कार्यों को विशेष रूप से पकड़ने के लिए अतिभारित किया जा सकता है। एक उदाहरण के लिए यहाँ देखें ।
जस्टिन टाइम -

5
0 कभी भी एक शून्य सूचक नहीं था, शून्य सूचक एक सूचक है जो शून्य प्रकार के सूचक को सूचक प्रकार से कास्टिंग करके प्राप्त किया जा सकता है , और यह परिभाषा द्वारा किसी भी मौजूदा वस्तु को इंगित नहीं करता है ।
स्विफ्ट - शुक्रवार पाई

जवाबों:


403

यह एक कीवर्ड और एक प्रकार का उदाहरण कैसे है?

यह आश्चर्य की बात नहीं है। दोनों trueऔर falseकीवर्ड हैं और शाब्दिक रूप में वे एक प्रकार है ( bool)। nullptrएक पॉइंटर का शाब्दिक प्रकार है std::nullptr_t, और यह एक प्रचलन है (आप इसका उपयोग करके इसका पता नहीं लगा सकते हैं &)।

  • 4.10पॉइंटर रूपांतरण के बारे में कहते हैं कि एक प्रकार std::nullptr_tका प्रचलन एक अशक्त पॉइंटर स्थिरांक है, और यह कि एक अभिन्न अशक्त पॉइंटर निरंतर में परिवर्तित किया जा सकता है std::nullptr_t। विपरीत दिशा की अनुमति नहीं है। यह पॉइंटर्स और पूर्णांक दोनों के लिए एक फ़ंक्शन को ओवरलोड करने की अनुमति देता है, और nullptrपॉइंटर संस्करण का चयन करने के लिए गुजरता है। पास करना NULLया 0भ्रमित करना intसंस्करण का चयन करना होगा ।

  • एक nullptr_tअभिन्न प्रकार के कलाकारों को एक की आवश्यकता होती है reinterpret_cast, और (void*)0अभिन्न प्रकार के मानचित्रण के रूप में एक ही शब्दार्थ होता है (परिभाषित मानचित्रण)। A किसी भी सूचक प्रकार में reinterpret_castपरिवर्तित नहीं हो सकता है nullptr_t। यदि संभव हो या उपयोग करें तो निहित रूपांतरण पर भरोसा करें static_cast

  • मानक की आवश्यकता है कि sizeof(nullptr_t)हो sizeof(void*)


ओह, देखने के बाद, ऐसा लगता है कि सशर्त ऑपरेटर 0 को nullptr में नहीं बदल सकते हैं जैसे कि मामलों में cond ? nullptr : 0;। मेरे उत्तर से हटा दिया गया।
जोहान्स शहाब -

88
ध्यान दें कि NULLहोने की गारंटी भी नहीं है 0। यह हो सकता है 0L, जिस स्थिति में कॉल करना void f(int); void f(char *);अस्पष्ट होगा। nullptrहमेशा पॉइंटर संस्करण का पक्ष लेगा, और कभी भी कॉल नहीं करेगा int। यह भी ध्यान दें कि nullptr यह परिवर्तनीय है bool(मसौदा कहता है कि पर 4.12)।
जोहान्स शाउब -

@ एलिट: तो एफ (इंट) और एफ (शून्य *) के संबंध में - एफ (0) अभी भी अस्पष्ट होगा?
स्टीव फॉली

27
@Steve, नहीं, जो intसंस्करण को कॉल करेगा । लेकिन f(0L)अस्पष्ट है, क्योंकि long -> intaswell long -> void*दोनों समान रूप से महंगा है। इसलिए यदि NULL 0Lआपके कंपाइलर पर है, तो एक कॉल f(NULL)अस्पष्ट रूप से उन दो कार्यों को दिया जाएगा। nullptrबेशक ऐसा नहीं है ।
जोहान्स स्काउब -

2
@ SvenS इसे (void*)0C ++ में परिभाषित नहीं किया जाना चाहिए । लेकिन इसे किसी भी मनमाने ढंग से अशक्त सूचक के रूप में परिभाषित किया जा सकता है, जो मान 0 और पूर्ण के साथ किसी भी अभिन्न निरंतर है nullptr। तो, निश्चित रूप से नहीं , लेकिन कर सकते हैं । (आप मुझे पिंग करना भूल गए btw ..)
डेडुप्लिकेटर

60

से nullptr: एक प्रकार-सुरक्षित और स्पष्ट अशक्त सूचक :

नया C ++ 09 nullptr कीवर्ड एक रिवाल्यू स्थिरांक को नामित करता है जो एक सार्वभौमिक नल पॉइंटर शाब्दिक के रूप में कार्य करता है, जो छोटी गाड़ी और कमजोर टाइप के शाब्दिक 0 और बदनाम NULL मैक्रो की जगह लेता है। nullptr इस प्रकार शर्मिंदगी, अस्पष्टता, और कीड़े के 30 से अधिक वर्षों के लिए एक अंत डालता है। निम्नलिखित खंड nullptr सुविधा प्रस्तुत करते हैं और बताते हैं कि यह NULL और 0 की बीमारियों को कैसे माप सकता है।

अन्य संदर्भ:


17
सी ++ 09? क्या इसे अगस्त 2011 से पहले C ++ 0x के रूप में संदर्भित नहीं किया गया था?
माइकल डोरस्ट

2
@anthropomorphic खैर इसका उद्देश्य है। C ++ 0x का उपयोग तब किया गया था जब यह अभी भी प्रगति पर था, क्योंकि यह नहीं पता था कि यह 2008 या 2009 में समाप्त हो जाएगा। ध्यान दें कि यह वास्तव में C ++ 0B का अर्थ C ++ 11 हो गया था। देखें stroustrup.com/C+11FAQ.html
mxmlnkn

44

C ++ 11 में nullptr क्यों? यह क्या है? NULL पर्याप्त क्यों नहीं है?

C ++ विशेषज्ञ एलेक्स एलेन कहते हैं कि यह पूरी तरह से यहाँ है (मेरा जोर बोल्ड में जोड़ा गया है):

... कल्पना कीजिए कि आपके पास निम्नलिखित दो कार्य घोषणाएँ हैं:

void func(int n); 
void func(char *s);

func( NULL ); // guess which function gets called?

यद्यपि ऐसा लगता है कि दूसरे फ़ंक्शन को बुलाया जाएगा - आप हैं, आखिरकार, जो एक पॉइंटर लगता है उसमें गुजर रहा है - यह वास्तव में पहला फ़ंक्शन है जिसे कहा जाएगा! परेशानी यह है कि क्योंकि NULL 0 है, और 0 एक पूर्णांक है, इसके बजाय func का पहला संस्करण कहा जाएगा। यह इस तरह की बात है कि, हाँ, हर समय नहीं होता है, लेकिन जब ऐसा होता है, तो बहुत निराशा होती है और भ्रमित होते हैं। यदि आपको यह पता नहीं है कि क्या चल रहा है, तो यह एक संकलक बग जैसा दिख सकता है। एक भाषा सुविधा जो संकलक बग की तरह दिखती है, ठीक है, न कि कुछ जिसे आप चाहते हैं।

Nullptr दर्ज करें। C ++ 11 में, nullptr एक नया कीवर्ड है जो NULL पॉइंटर्स का प्रतिनिधित्व करने के लिए (और!) किया जाना चाहिए। दूसरे शब्दों में, जहाँ भी आप NULL से पहले लिख रहे थे, आपको इसके बजाय nullptr का उपयोग करना चाहिए। यह आपके लिए और अधिक स्पष्ट नहीं है, प्रोग्रामर , (हर कोई जानता है कि NULL का मतलब क्या है), लेकिन यह संकलक के लिए अधिक स्पष्ट है , जो अब 0s को हर जगह नहीं दिखाई देगा, जिसका उपयोग एक संकेतक के रूप में उपयोग किए जाने पर विशेष अर्थ के लिए किया जा रहा है।

एलन ने अपने लेख को समाप्त किया:

इस सब के बावजूद - सी ++ 11 के लिए अंगूठे का नियम बस का उपयोग करना शुरू करना है nullptrजब भी आप अन्यथा NULLअतीत में उपयोग करते होंगे ।

(मेरे शब्द):

अंत में, यह मत भूलो कि nullptrएक वस्तु है - एक वर्ग। इसे NULLपहले कहीं भी इस्तेमाल किया जा सकता है , लेकिन यदि आपको किसी कारण से इसके प्रकार की आवश्यकता है, तो इसे टाइप किया जा सकता है decltype(nullptr), या सीधे रूप में वर्णित किया जा सकता है std::nullptr_t, जो कि केवल एक typedefहैdecltype(nullptr)

संदर्भ:

  1. Cprogramming.com: C ++ 11 में बेहतर प्रकार - nullptr, enum classes (दृढ़ता से टाइप की गई गणना) और cstdint
  2. https://en.cppreference.com/w/cpp/language/decltype
  3. https://en.cppreference.com/w/cpp/types/nullptr_t

2
मुझे कहना होगा कि आपका उत्तर रेखांकित है, आपके उदाहरण के माध्यम से समझना बहुत आसान था।
एमएस

37

जब आपके पास एक फ़ंक्शन होता है जो एक से अधिक प्रकार के लिए संकेत प्राप्त कर सकता है, तो इसके साथ कॉल करना NULLअस्पष्ट है। जिस तरह से यह चारों ओर काम किया जाता है वह एक इंट को स्वीकार करके और इसे मानकर बहुत हैक किया जाता है NULL

template <class T>
class ptr {
    T* p_;
    public:
        ptr(T* p) : p_(p) {}

        template <class U>
        ptr(U* u) : p_(dynamic_cast<T*>(u)) { }

        // Without this ptr<T> p(NULL) would be ambiguous
        ptr(int null) : p_(NULL)  { assert(null == NULL); }
};

इसमें C++11आप ओवरलोड करने में सक्षम होंगे nullptr_tताकि ptr<T> p(42);एक रन-टाइम के बजाय एक संकलन-समय त्रुटि होगी assert

ptr(std::nullptr_t) : p_(nullptr)  {  }

क्या होगा अगर NULLके रूप में परिभाषित किया गया है 0L?
एलएफ

9

nullptr अभिन्न प्रकार को नहीं सौंपा जा सकता है जैसे कि ए int लेकिन केवल एक सूचक प्रकार; या तो अंतर्निहित पॉइंटर प्रकार जैसे int *ptrया स्मार्ट पॉइंटर जैसे किstd::shared_ptr<T>

मेरा मानना ​​है कि यह एक महत्वपूर्ण अंतर है क्योंकि NULLअभी भी एक अभिन्न प्रकार और एक संकेतक दोनों को सौंपा जा सकता है क्योंकि NULLएक मैक्रो का विस्तार किया गया है 0जो प्रारंभिक मूल्य के intसाथ-साथ एक सूचक के रूप में भी काम कर सकता है ।


ध्यान दें कि यह उत्तर गलत है। NULLको विस्तारित करने की गारंटी नहीं है 0
LF

6

इसके अलावा, क्या आपके पास एक और उदाहरण है (विकिपीडिया के बगल में) जहां nullptrअच्छा पुराने 0 से बेहतर है?

हाँ। यह एक (सरलीकृत) वास्तविक दुनिया का उदाहरण है जो हमारे उत्पादन कोड में हुआ है। यह केवल बाहर खड़ा था क्योंकि gcc एक चेतावनी जारी करने में सक्षम था जब अलग-अलग रजिस्टर चौड़ाई के साथ एक प्लेटफ़ॉर्म को पार कर रहा था (अभी भी निश्चित रूप से निश्चित नहीं है कि केवल जब x86_64 से x86 तक क्रॉसकंपलिंग करता है, तो चेतावनी देता हैwarning: converting to non-pointer type 'int' from NULL ):

इस कोड पर विचार करें (C ++ 03):

#include <iostream>

struct B {};

struct A
{
    operator B*() {return 0;}
    operator bool() {return true;}
};

int main()
{
    A a;
    B* pb = 0;
    typedef void* null_ptr_t;
    null_ptr_t null = 0;

    std::cout << "(a == pb): " << (a == pb) << std::endl;
    std::cout << "(a == 0): " << (a == 0) << std::endl; // no warning
    std::cout << "(a == NULL): " << (a == NULL) << std::endl; // warns sometimes
    std::cout << "(a == null): " << (a == null) << std::endl;
}

इससे यह उत्पादन प्राप्त होता है:

(a == pb): 1
(a == 0): 0
(a == NULL): 0
(a == null): 1

मैं यह देखने में विफल रहता हूं कि nullptr (और C ++ 11) का उपयोग करते समय यह कैसे सुधरता है। यदि आप pb को nullptr पर सेट करते हैं तो पहली तुलना अभी भी सही है (जबकि नाशपाती के साथ सेब की तुलना करते हुए)। दूसरा मामला और भी बुरा है: यदि आप nullptr से तुलना करते हैं तो यह a को B * में बदल देगा और फिर यह फिर से सही होने का मूल्यांकन करेगा (इससे पहले कि इसे बूल में डाला गया था और एक्‍सआर का गलत मूल्यांकन किया गया था)। पूरी बात मुझे जावास्क्रिप्ट की याद दिलाती है और मुझे आश्चर्य है कि अगर हमें भविष्य में C ++ में === मिलेगा :(
Nils

5

खैर, अन्य भाषाओं में आरक्षित शब्द हैं जो प्रकार के उदाहरण हैं। उदाहरण के लिए पायथन:

>>> None = 5
  File "<stdin>", line 1
SyntaxError: assignment to None
>>> type(None)
<type 'NoneType'>

यह वास्तव में एक काफी करीबी तुलना है क्योंकि Noneआमतौर पर ऐसी चीज के लिए उपयोग किया जाता है जिसे किसी भी चीज के लिए उपयोग नहीं किया गया है, लेकिन साथ ही साथ तुलना भीNone == 0 झूठी हैं।

दूसरी ओर, सादे सी में, NULL == 0सही IIRC लौटाएगा क्योंकि NULLसिर्फ एक मैक्रो 0 है, जो हमेशा एक अमान्य पता (AFAIK) है।


4
NULLएक मैक्रो है जो एक शून्य तक फैलता है, एक पॉइंटर के लिए एक निरंतर शून्य कास्ट एक शून्य पॉइंटर का उत्पादन करता है। एक शून्य सूचक शून्य नहीं होना चाहिए (लेकिन अक्सर होता है), शून्य हमेशा एक अमान्य पता नहीं होता है, और एक सूचक के लिए एक गैर-निरंतर शून्य डाली शून्य होना आवश्यक नहीं है, और एक शून्य सूचक डाली जाती है पूर्णांक शून्य नहीं होना चाहिए। मुझे आशा है कि मुझे कुछ भी भूलने के बिना सब ठीक हो गया। एक संदर्भ: c-faq.com/null/null2.html
सैमुअल एडविन वार्ड

3

यह एक कीवर्ड है क्योंकि मानक इसे इस तरह निर्दिष्ट करेगा। ;-) नवीनतम सार्वजनिक मसौदे के अनुसार (n2914)

२.१४.ull पॉइंटर लिटरल [lex.nullptr]

pointer-literal:
nullptr

पॉइंटर शाब्दिक कीवर्ड है nullptr। यह प्रकार का एक प्रकार है std::nullptr_t

यह उपयोगी है क्योंकि यह अभिन्न रूप से अभिन्न मूल्य में परिवर्तित नहीं होता है।


2

मान लें कि आपके पास एक फ़ंक्शन (एफ) है जो इंट और चार दोनों लेने के लिए अतिभारित है। C ++ 11 से पहले, यदि आप इसे अशक्त सूचक के साथ कॉल करना चाहते थे, और आपने NULL (यानी मान 0) का उपयोग किया, तो आप int के लिए अतिभारित कॉल करेंगे:

void f(int);
void f(char*);

void g() 
{
  f(0); // Calls f(int).
  f(NULL); // Equals to f(0). Calls f(int).
}

यह शायद वह नहीं है जो आप चाहते थे। C ++ 11 इसे nullptr के साथ हल करता है; अब आप निम्नलिखित लिख सकते हैं:

void g()
{
  f(nullptr); //calls f(char*)
}

1

मुझे सबसे पहले आपको अनफ्रेंडिफ़िकेशन लागू करना चाहिए nullptr_t

struct nullptr_t 
{
    void operator&() const = delete;  // Can't take address of nullptr

    template<class T>
    inline operator T*() const { return 0; }

    template<class C, class T>
    inline operator T C::*() const { return 0; }
};

nullptr_t nullptr;

nullptrवापसी प्रकार रिज़ॉल्वर मुहावरे का एक सूक्ष्म उदाहरण स्वचालित रूप से सही प्रकार के अशक्त सूचक को कम करने के लिए है जो उस प्रकार के उदाहरण पर निर्भर करता है जिसे वह असाइन कर रहा है।

int *ptr = nullptr;                // OK
void (C::*method_ptr)() = nullptr; // OK
  • जैसा कि आप ऊपर, जब nullptrएक पूर्णांक सूचक को सौंपा जा रहा है , तो inttemplatized रूपांतरण फ़ंक्शन का एक प्रकार इंस्टेंटेशन बनाया जाता है। और वही विधि संकेत के लिए भी जाता है।
  • इस तरह से टेम्पलेट कार्यक्षमता का लाभ उठाते हुए, हम वास्तव में हर बार जब हम करते हैं, तो एक नए प्रकार का असाइनमेंट उपयुक्त प्रकार का नल पॉइंटर बनाते हैं।
  • जैसा कि nullptrमूल्य शून्य के साथ पूर्णांक शाब्दिक है, आप इसके पते का उपयोग करने में सक्षम नहीं हो सकते हैं, जिसे हमने हटाने और ऑपरेटर द्वारा पूरा किया है।

हमें nullptrपहली जगह की आवश्यकता क्यों है ?

  • आप देखते हैं कि पारंपरिक NULLमें इसके साथ कुछ समस्याएँ हैं:

1। अव्यवस्थित रूपांतरण

char *str = NULL; // Implicit conversion from void * to char *
int i = NULL;     // OK, but `i` is not pointer type

2 फ़ंक्शन कॉलिंग अस्पष्टता

void func(int) {}
void func(int*){}
void func(bool){}

func(NULL);     // Which one to call?
  • संकलन निम्नलिखित त्रुटि पैदा करता है:
error: call to 'func' is ambiguous
    func(NULL);
    ^~~~
note: candidate function void func(bool){}
                              ^
note: candidate function void func(int*){}
                              ^
note: candidate function void func(int){}
                              ^
1 error generated.
compiler exit status 1

3 कंस्ट्रक्टर ओवरलोड

struct String
{
    String(uint32_t)    {   /* size of string */    }
    String(const char*) {       /* string */        }
};

String s1( NULL );
String s2( 5 );
  • ऐसे मामलों में, आपको स्पष्ट डाली (यानी की जरूरत है  String s((char*)0))

0

0 केवल पूर्णांक मान के रूप में उपयोग किया जाता है जो कि पॉइंटर्स के लिए कास्ट-फ्री इनिशियलाइज़र के रूप में उपयोग किया जा सकता है: आप बिना किसी कास्ट के अन्य पूर्णांक मान के साथ पॉइंटर्स को इनिशियलाइज़ नहीं कर सकते। आप 0 को एक पूर्णांक शाब्दिक के समान सिंटेक्स सिंगल्सटन मान सकते हैं। यह किसी भी पॉइंटर या पूर्णांक को आरंभ कर सकता है। लेकिन आश्चर्यजनक रूप से, आप पाएंगे कि इसका कोई अलग प्रकार नहीं है: यह एक है int। तो 0 कैसे आ सकते हैं पॉइंटर्स को इनिशियलाइज़ कर सकते हैं और 1 नहीं कर सकते? एक व्यावहारिक उत्तर यह था कि हमें सूचक शून्य मान को परिभाषित करने के साधन की आवश्यकता थी और intएक सूचक का प्रत्यक्ष निहित रूपांतरण त्रुटि-प्रवण है। इस प्रकार 0 प्रागैतिहासिक युग से बाहर एक वास्तविक सनकी अजीब जानवर बन गया। nullptrबिंदुओं को आरम्भ करने के लिए शून्य मान का वास्तविक सिंगलटन कॉन्स्ट्रेप प्रतिनिधित्व होना प्रस्तावित था। यह सीधे पूर्णांक को इनिशियलाइज़ करने के लिए इस्तेमाल नहीं किया जा सकता है और NULL0. के संदर्भ में परिभाषित करने के साथ शामिल अस्पष्टताओं को समाप्त करता है, nullptrजिसे एसटीडी सिंटैक्स का उपयोग करके एक लाइब्रेरी के रूप में परिभाषित किया जा सकता है लेकिन शब्दार्थ एक लापता कोर घटक माना जाता है। NULLअब के पक्ष में nullptrतब तक पदावनत किया जाता है , जब तक कि कुछ पुस्तकालय इसे परिभाषित नहीं करते nullptr


-1

यहाँ LLVM हैडर है।

// -*- C++ -*-
//===--------------------------- __nullptr --------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP_NULLPTR
#define _LIBCPP_NULLPTR

#include <__config>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#pragma GCC system_header
#endif

#ifdef _LIBCPP_HAS_NO_NULLPTR

_LIBCPP_BEGIN_NAMESPACE_STD

struct _LIBCPP_TEMPLATE_VIS nullptr_t
{
    void* __lx;

    struct __nat {int __for_bool_;};

    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t() : __lx(0) {}
    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t(int __nat::*) : __lx(0) {}

    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator int __nat::*() const {return 0;}

    template <class _Tp>
        _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
        operator _Tp* () const {return 0;}

    template <class _Tp, class _Up>
        _LIBCPP_INLINE_VISIBILITY
        operator _Tp _Up::* () const {return 0;}

    friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator==(nullptr_t, nullptr_t) {return true;}
    friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator!=(nullptr_t, nullptr_t) {return false;}
};

inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t __get_nullptr_t() {return nullptr_t(0);}

#define nullptr _VSTD::__get_nullptr_t()

_LIBCPP_END_NAMESPACE_STD

#else  // _LIBCPP_HAS_NO_NULLPTR

namespace std
{
    typedef decltype(nullptr) nullptr_t;
}

#endif  // _LIBCPP_HAS_NO_NULLPTR

#endif  // _LIBCPP_NULLPTR

(एक महान सौदा एक त्वरित के साथ खुला हो सकता है grep -r /usr/include/*`)

एक चीज जो बाहर कूदती है वह है ऑपरेटर *ओवरलोड (0 लौटना सेगफॉल्टिंग की तुलना में बहुत अधिक मित्रवत है ...)। एक और बात यह है कि यह एक पते को संग्रहीत करने के साथ बिल्कुल भी संगत नहीं दिखता है । इसकी तुलना में, यह कैसे स्लिंगिंग शून्य * की ओर जाता है और सामान्य परिणामों को सेंटिनल मान के रूप में NULL परिणाम देता है, जाहिर है कि "कभी न भूलें, यह एक बम हो सकता है" कारक है।


-2

NULL की आवश्यकता नहीं है 0. जब तक आप हमेशा NULL और 0 का उपयोग करते हैं, NULL का कोई मूल्य नहीं हो सकता है। मान लें कि आप फ्लैट मेमोरी के साथ एक वॉन नीमन माइक्रोकंट्रोलर प्रोग्राम करते हैं, जिसमें 0.90 पर इसकी इंटरप्ट वीकेटर्स हैं और यदि NULL 0 है और कुछ NULL पॉइंटर माइक्रोकंट्रोलर क्रैश में लिखता है। यदि NULL 1024 को कहने की अनुमति देता है और 1024 में एक आरक्षित चर है, तो लेखन इसे क्रैश नहीं करेगा, और आप प्रोग्राम के अंदर से NULL Pointer असाइनमेंट का पता लगा सकते हैं। यह पीसी पर व्यर्थ है, लेकिन अंतरिक्ष जांच, सैन्य या चिकित्सा उपकरणों के लिए यह महत्वपूर्ण है कि दुर्घटना न हो।


2
ठीक है, मेमोरी में नल पॉइंटर का वास्तविक मान शून्य नहीं हो सकता है, लेकिन C (और C ++) मानक अनिवार्य संकलक को अभिन्न 0 शाब्दिक को अशक्त सूचक में बदलने के लिए मजबूर करता है।
bzim
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.