Issues on pointers

Hi,

Is nullptr the same and equal to zero? We use a pointer that we assigned nullptr to that in if conditions. And if conditions work only on zero or non-zero.
Like: if(ptr) ...
So if these are all true why not using zero (0) instead of that newly suggested nullptr, please?

Another question:
If we declare a local variable in a function, that variable will be destroyed by going out of its scope. But when we declare a local pointer instead of that variable and assign an object to it using new, the pointer won't be destroyed even if it goes out of its scope and we should use delete for it. Why is there this difference please?
Last edited on
And if conditions work only on zero or non-zero.

Rather, they work on false and true. It just so happens that 0 converts to false and non-zero converts to true, but this isn't fundamental.

The keyword nullptr exists to eliminate the ambiguities caused by using the integer 0 (or the equivalent macro NULL) in a context where a pointer is intended. Consider:
1
2
3
4
# include <iostream>
void f(int)  { std::cout << "f(int) called\n"; }
void f(int*) { std::cout << "f(int*) called\n"; }
int main() {  f(NULL); f(nullptr); } 
f(int) called
f(int*) called


Usually, integers are not convertible to pointers. But the integer 0 (and the equivalent macro NULL) is handled specially. The standard says that among integers, only a prvalue 0 is considered a null pointer constant, and only it can be converted to any pointer type. nullptr isn't convertible to integral types (int, long, etc.) but only to other pointers (and bool), and it converts to false or the corresponding null pointer value, respectively.

But when we declare a local pointer instead of that variable and assign an object to it using new, the pointer won't be destroyed even if it goes out of its scope and we should use delete for it. Why is there this difference please?

The pointer itself will be destroyed. It's the resource that that pointer refers to which must be explicitly released by delete.

The pointed-to resource isn't freed automatically because new exists to give control over the lifetime of an object to the programmer. I saw your other question -- how else could std::vector store objects if the object was always destroyed only shortly after it was new'd?

This is a simplification, to some extent. The real answer is related to the discussion of ownership. For the special case of pointers (really pointer-like resources), the standard library supplies some utilities to help keep track of who is responsible for any particular resource, called smart pointers.


Last edited on
With void f(int); and void f(int*); declared, for f(NULL); a conforming inplementation may:

a. resolve the call to f(int) - the implementation has #define NULL 0

b. resolve the call to f(int*) - the implementation has #define NULL nullptr

c. give an ambiguous call of overload function error - the implementation has
#define NULL some_implementation_defined_type_which_gives_this_error

For example, with g++, we have #define NULL __null where __null is a compiler intrinsic.
http://coliru.stacked-crooked.com/a/c48235cb9a511263
Yes, that's a good point (NULL isn't always 0). Thanks.
Maybe the example would be better using 0 instead.
Last edited on
while most systems use null = 0 and nullptr = 0, you should use the keyword in the if statement for clarity.

if(ptr == nullptr) instead of these: if(ptr == 0) or if(ptr); //all three work on almost all systems, but you don't want to fix 1000000000 lines of code when you move it to a system where nullptr = -1 or something weird.

------
in a function, the POINTER variable is destroyed but the MEMORY allocated by NEW is still claimed and in use. If you were able to capture a pointer to that memory, it can still be used. If you did not, its a memory leak, that memory is "lost" (on modern OS, when the program ends the OS will get it back, but for long running programs, this kind of leak can eventually run the OS out of memory).


The standard requires that the keyword nullptr be a literal prvalue of type std::nullptr_t.
Implementations do not have any choice in the matter.

If ptr is a pointer, these three are guaranteed to be equivalent in every implementation:
if( ptr == nullptr ), if( ptr == 0 ) and if(!ptr)

And these three are equivalent:
if( ptr != nullptr ), if( ptr != 0 ) and if(ptr)
Last edited on
so is it zero or not?

"if( ptr == 0 ) and if(ptr)" ? always works?

"Yes, that's a good point (NULL isn't always 0). Thanks."


Last edited on
NULL need not be 0, but you may use 0 regardless of what NULL is.
If NULL is defined to be an integer literal, it must be an integer literal with a value of zero.

However, there is no requirement that NULL must be defined to be an integer literal.
For two other ways in which NULL can be defined, see:
http://www.cplusplus.com/forum/general/221825/#msg1018299
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>

void foo( const int* ) { std::cout << "const int*\n" ; }
void foo( const void* ) { std::cout << "const void*\n" ; }
void foo( std::nullptr_t ) { std::cout << "std::nullptr_t\n" ; }

int main()
{
    int i = 0 ;
    foo( std::addressof(i) ) ; // const int*
    int* pi = nullptr ; // type of pi is int*
    foo(pi) ; // const int*

    double d = 0 ;
    foo( std::addressof(d) ) ; // const void*
    double* pd = nullptr ; // type of pd is double*
    foo(pd) ; // const void*

    foo(nullptr) ; // std::nullptr_t (type of nullptr is std::nullptr_t )

    const auto np1 = nullptr ; // type of np1 is std::nullptr_t
    foo(np1) ; // std::nullptr_t

    std::nullptr_t np2 = 0 ; // type of np2 is std::nullptr_t
    foo(np2) ; // std::nullptr_t

    // foo(0) ; // *** error: ambiguous: 1. foo( (const int*)0 ) ;
    //                                   2. foo( (const void*)0 ) ;
    //                                   3. foo( std::nullptr_t(0) ) ;
}

http://coliru.stacked-crooked.com/a/4620e46c773b0542
http://rextester.com/DHVC67117
Thank you all very much.
Topic archived. No new replies allowed.