
- C++ Home
- C++ Overview
- C++ Environment Setup
- C++ Basic Syntax
- C++ Comments
- C++ Hello World
- C++ Omitting Namespace
- C++ Tokens
- C++ Constants/Literals
- C++ Keywords
- C++ Identifiers
- C++ Data Types
- C++ Numeric Data Types
- C++ Character Data Type
- C++ Boolean Data Type
- C++ Variable Types
- C++ Variable Scope
- C++ Multiple Variables
- C++ Input Output Operations
- C++ Basic Input/Output
- C++ Cin
- C++ Cout
- C++ Manipulators
- Type System & Data Representation
- C++ Modifier Types
- C++ Storage Classes
- C++ Constexpr Specifier
- C++ Numbers
- C++ Enumeration
- C++ Enum Class
- C++ References
- C++ Date & Time
- C++ Operators
- C++ Operators
- C++ Arithmetic Operators
- C++ Relational Operators
- C++ Logical Operators
- C++ Bitwise Operators
- C++ Assignment Operators
- C++ sizeof Operator
- C++ Conditional Operator
- C++ Comma Operator
- C++ Member Operators
- C++ Casting Operators
- C++ Pointer Operators
- C++ Operators Precedence
- C++ Unary Operators
- C++ Scope Resolution Operator
- C++ Control Statements
- C++ Decision Making
- C++ if Statement
- C++ if else Statement
- C++ Nested if Statements
- C++ switch Statement
- C++ Nested switch Statements
- C++ Loop Types
- C++ while Loop
- C++ for Loop
- C++ do while Loop
- C++ Foreach Loop
- C++ Nested Loops
- C++ Jump Statements
- C++ break Statement
- C++ continue Statement
- C++ goto Statement
- C++ Return Values
- C++ Strings
- C++ Strings
- C++ Loop Through a String
- C++ String Length
- C++ String Concatenation
- C++ String Comparison
- C++ Functions
- C++ Functions
- C++ Multiple Function Parameters
- C++ Recursive Function
- C++ Function Overloading
- C++ Function Overriding
- C++ Default Arguments
- C++ Arrays
- C++ Arrays
- C++ Multidimensional Arrays
- C++ Pointer to an Array
- C++ Passing Arrays to Functions
- C++ Return Array from Functions
- C++ Array Decay
- C++ Structure & Union
- C++ Structures
- C++ Unions
- C++ Class and Objects
- C++ Object Oriented
- C++ Classes & Objects
- C++ Class Member Functions
- C++ Class Access Modifiers
- C++ Static Class Members
- C++ Static Data Members
- C++ Static Member Function
- C++ Inline Functions
- C++ this Pointer
- C++ Friend Functions
- C++ Pointer to Classes
- C++ Constructors
- C++ Constructor & Destructor
- C++ Default Constructors
- C++ Parameterized Constructors
- C++ Copy Constructor
- C++ Constructor Overloading
- C++ Constructor with Default Arguments
- C++ Delegating Constructors
- C++ Constructor Initialization List
- C++ Dynamic Initialization Using Constructors
- C++ Destructors
- C++ Virtual Destructor
- C++ Inheritance
- C++ Inheritance
- C++ Multiple Inheritance
- C++ Multilevel Inheritance
- C++ Object-oriented
- C++ Overloading
- C++ Polymorphism
- C++ Abstraction
- C++ Encapsulation
- C++ Interfaces
- C++ Virtual Function
- C++ Pure Virtual Functions & Abstract Classes
- C++ Override Specifiers
- C++ Final Specifiers
- C++ Design Patterns
- C++ Creational Design Patterns
- C++ Singleton Design Pattern
- C++ Factory Method Design Pattern
- C++ Abstract Factory Pattern
- C++ Prototype Design Pattern
- C++ Structural Design Patterns
- C++ File Handling
- C++ Files and Streams
- C++ Reading From File
- C++ Advanced
- C++ Exception Handling
- C++ Dynamic Memory
- C++ Namespaces
- C++ Templates
- C++ Preprocessor
- C++ Signal Handling
- C++ Multithreading
- C++ Web Programming
- C++ Socket Programming
- C++ Concurrency
- C++ Advanced Concepts
- C++ Lambda Expression
- C++ nullptr
- C++ unordered_multiset
- C++ Structural Design Patterns
- C++ Adapter Pattern
- C++ Bridge Pattern
- C++ Composite Pattern
- C++ Decorator Pattern
nullptr in C++
The nullptr keyword in C++ represents a null pointer value which was earlier represented using NULL or 0. It was introduced in C++11 and is of type std::nullptr_t. The nullptr is a type-safe pointer that is implicitly convertible and can be compared to any pointer.
The syntax for defining a nullptr is given below −
int* ptr = nullptr; // ptr is a null pointer of type int*
Example
The following example demonstrates how to use nullptr in C++
#include <iostream> using namespace std; int main() { int *ptr = nullptr; // ptr is a null pointer if (ptr == nullptr) { cout << "Pointer is null." << endl; } else { cout << "Pointer is not null." << endl; } int x = 10; ptr = &x; if (ptr != nullptr) { cout << "Pointer now points to: " << *ptr << endl; } return 0; }
The output of the above code is given below −
Pointer is null. Pointer now points to: 10
Why Do We Need nullptr?
We need nullptr because of the following problems caused by using NULL or 0
Ambiguity in Function Calling
Calling a function with value '0' to represent NULL creates an ambiguity because compiler treats '0' as an integer value rather than a null pointer.
In this example, we are calling display() function by passing value as '0'. It calls the function that has an int parameter rather than calling the function that has a pointer in its parameter.
#include <iostream> using namespace std; void display(int n){ cout << "Calling display function with int" << endl; } void display(int *p){ cout << "Calling display function with int*" << endl; } int main(){ display(0); // Ambiguous call as Compiler treats 0 as integer return 0; }
The output of the above code is given below −
Calling display function with int
Solution: Below is the solution to above problem where we have used nullptr that calls the display() function that has a pointer in its parameter −
#include <iostream> using namespace std; void display(int n){ cout << "Calling display function with int" << endl; } void display(int *p){ cout << "Calling display function with int*" << endl; } int main(){ display(nullptr); return 0; }
The output of the above code is given below −
Calling display function with int*
Problem in Function Overloading
If you call an overloaded function with NULL value, it will cause a compilation error. The NULL is valid for both parameters that is int and int*. So, in this confusion compiler throws an error. Below is an example to demonstrate this problem.
#include <iostream> using namespace std; class Demo{ public: void show(int n) { cout << "Calling show() function with int" << endl; } void show(int *p) { cout << "Calling show() function with int*" << endl; } }; int main() { Demo obj; // Ambiguous call with NULL obj.show(NULL); return 0; }
The output of the above code is given below −
main.cpp: In function 'int main()': main.cpp:22:17: error: call of overloaded 'show(NULL)' is ambiguous 22 | obj.show(NULL); | ~~~~~~~~^~~~~~ main.cpp:7:14: note: candidate: 'void Demo::show(int)' 7 | void show(int n) | ^~~~ main.cpp:12:14: note: candidate: 'void Demo::show(int*)' 12 | void show(int *p) | ^~~~
Solution: Below is the solution to above problem where we have used nullptr that calls the display() function that has a pointer in its parameter −
#include <iostream> using namespace std; class Demo { public: void show(int n) { cout << "Calling show() function with int" << endl; } void show(int *p) { cout << "Calling show() function with int*" << endl; } }; int main() { Demo obj; obj.show(nullptr); // Correctly calls int* function return 0; }
The output of the above code is given below −
Calling show() function with int*
Type-Safety Problem
The NULL is treated as an integer since it is defined with '0'. It creates the same ambiguity as the above two problems. It is solved using nullptr because nullptr is type-safe unlike NULL and it is implicitly convertible to any pointer type.
#include <iostream> using namespace std; int main() { int* ptr = nullptr; cout << "Comparing with NULL" << endl; if (ptr == NULL) { cout << "NULL is TRUE" << endl; } else { cout << "NULL is FALSE" << endl; } cout << "\nComparing with nullptr" << endl; if (ptr == nullptr) { cout << "nullptr is TRUE" << endl; } else { cout << "nullptr is FALSE" << endl; } int value = 0; // NULL will be treated as integer 0 if (value == NULL) { cout << "value(0) = NULL is TRUE" << endl; } return 0; }
The output of the above code is given below −
main.cpp: In function 'int main()': main.cpp:24:22: warning: NULL used in arithmetic [-Wpointer-arith] 24 | if (value == NULL) | ^~~~ Comparing with NULL NULL is TRUE Comparing with nullptr nullptr is TRUE value(0) = NULL is TRUE
NULL vs nullptr
The difference between NULL and nullptr is mentioned in the table below −
NULL | nullptr |
---|---|
It is an integer constant that represents either 0 or 0L. In C, it is represented as ((void*)0). | It is a pointer literal of type std::nullptr_t. |
It is not type-safe as it may be treated as an int. | It is type-safe as it represents only pointer. |
It can be assigned to int values. | It can not be assigned to an int value, as it will show an error. |
In function overloading, there is ambiguity when calling the function. | It prevents the problem of ambiguity in function overloading. |
Example: int* p = NULL; | Example: int* p = nullptr; |
Nullptr Use Cases
The main purpose of the nullptr is to assign a null value to any pointer. Here are some use cases where a nullptr can be used.
Resetting Pointers After Deletion
A pointer needs to be assigned to a null value after deletion to avoid a dangling pointer. Here is an example to reset pointer to null after cleaning up the memory.
#include <iostream> using namespace std; int main() { int *ptr = new int(57); cout << "Value: " << *ptr << endl; delete ptr; // Free memory ptr = nullptr; // Resetting pointer if (ptr == nullptr) cout << "Pointer reset successful." << endl; return 0; }
The output of the above code is given below −
Value: 57 Pointer reset successful.
Checking Pointer Validity
You should first check that the pointer is not null before accessing it to avoid crashes. Here is an example to check if the pointer ptr is a null pointer or not.
#include <iostream> using namespace std; int main() { int *ptr = nullptr; if (ptr != nullptr) cout << "Pointer value: " << *ptr << endl; else cout << "It is a null pointer." << endl; return 0; }
The output of the above code is given below −
It is a null pointer.
Safe Object Initialization for Null Value
The nullptr can be used for setting a pointer to null without causing any error or any garbage value. Here is an example to assign a null value to represent an empty linked list −
#include <iostream> using namespace std; struct Node { int data; Node *next; }; int main() { Node *head = nullptr; // Empty linked list if (head == nullptr) cout << "Linked list is empty." << endl; return 0; }
The output of the above code is given below −
Linked list is empty.
Function Overloading Resolution
The nullptr is also used to resolve the ambiguity in function overloading. Here is an example.
#include <iostream> using namespace std; void show(int n){ cout << "Integer called." << endl; } void show(int *p){ cout << "Pointer called." << endl; } int main(){ show(nullptr); // Calls pointer return 0; }
The output of the above code is given below −
Pointer called.
Conclusion
In this chapter, we have understood that the nullptr in C++ is used when we need a null pointer. Before C++11, NULL was used, but it had various problems which is addressed by the nullptr. We have also discussed various use cases of nullptr with examples.