nullptr


Keyword: nullptr

nullptr is a keyword introduced in C++11 to represent a null pointer. It provides a type-safe way to denote a pointer that doesn't point to any object. nullptr is of type std::nullptr_t and can be implicitly converted to any pointer type.

Example 1: Basic Usage

#include <iostream>

void processPointer(int* ptr) {
    if (ptr == nullptr) {
        std::cout << "Null pointer received\n";
    } else {
        std::cout << "Value: " << *ptr << "\n";
    }
}

int main() {
    int* p1 = nullptr;
    int value = 42;
    int* p2 = &value;

    processPointer(p1);
    processPointer(p2);

    return 0;
}

Explanation

Example 2: Function Overloading

#include <iostream>

void foo(int i) {
    std::cout << "foo(int) called\n";
}

void foo(char* p) {
    std::cout << "foo(char*) called\n";
}

int main() {
    foo(0);        // Calls foo(int)
    foo(nullptr);  // Calls foo(char*)

    return 0;
}

Explanation

Example 3: Class Member Pointers

#include <iostream>

class MyClass {
public:
    void print() const { std::cout << "MyClass::print() called\n"; }
};

int main() {
    MyClass* obj = nullptr;
    void (MyClass::*memberFunc)() const = &MyClass::print;

    if (obj == nullptr) {
        std::cout << "obj is null, can't call member function\n";
    } else {
        (obj->*memberFunc)();
    }

    obj = new MyClass();
    (obj->*memberFunc)();

    delete obj;
    return 0;
}

Explanation

Safety and Best Practices

  1. Always initialize pointers to nullptr if they don't have a valid address to point to immediately.
  2. Use nullptr instead of NULL or 0 for null pointers to improve type safety and code readability.
  3. Implement null checks before dereferencing pointers to prevent undefined behavior.

Summary

nullptr is a crucial feature in modern C++ for representing null pointers. It offers several advantages over the older NULL macro:

  1. Type safety: nullptr is of type std::nullptr_t, which prevents accidental misuse with integral types.
  2. Clarity: It makes the code more readable by explicitly indicating a null pointer.
  3. Overload resolution: It helps in correctly resolving function overloads, as demonstrated in Example 2.

By using nullptr, developers can write safer and more expressive code when dealing with pointers. It's an essential tool for preventing null pointer dereferences and improving overall code quality in C++ programs.

Additional information

The reason why the code using nullptr compiles without warnings or errors, even though the default standard is C++98/C++03 (__cplusplus 199711L), is that many modern compilers, including GCC, implement a number of C++11 features as extensions even when the default language standard is set to an earlier version, such as C++98/C++03.

Key Points:

  1. Compiler Extensions:
  2. Compilers like GCC and Clang often include support for some features from newer standards, such as C++11, even when the code is being compiled under an older standard like C++98.
  3. nullptr is one of these features that is often supported as an extension. This allows code that uses nullptr to compile without explicitly enabling C++11.

  4. Backward Compatibility:

  5. Compiler developers often prioritize backward compatibility and ease of use. By including some newer features in older standards, they make it easier for developers to transition codebases to newer standards gradually, without breaking existing code.

  6. GCC's Behavior:

  7. In the specific case of GCC, it supports nullptr even when the default standard is C++98/C++03. The compiler does not strictly enforce the older standard if it's able to recognize and support newer constructs.
  8. As a result, when you use nullptr in a C++98 codebase, GCC recognizes it as valid even though nullptr was officially introduced in C++11.

Example 4: C++99

In the code below, it's unclear whether the call to foo(0) is meant to invoke the foo(int) or foo(void*) overload. The ambiguity arises because 0 can represent both a null pointer and an integer.

#include <iostream>

void foo(int value) {
    std::cout << "Integer overload: " << value << std::endl;
}

void foo(void* ptr) {
    std::cout << "Pointer overload: " << ptr << std::endl;
}

int main() {
    foo(0);  // Ambiguous: Is this calling foo(int) or foo(void*)?
    return 0;
}

Example 5: C++11

#include <iostream>

void foo(int value) {
    std::cout << "Integer overload: " << value << std::endl;
}

void foo(void* ptr) {
    std::cout << "Pointer overload: " << ptr << std::endl;
}

int main() {
    foo(nullptr);  // Clearly calls foo(void*)
    return 0;
}

Conclusion:

Even though the __cplusplus macro indicates that the compiler is using C++98 by default, GCC's support for nullptr as an extension means that the code compiles successfully without errors or warnings. This behavior is typical of GCC, which aims to provide a smooth transition path for developers adopting newer C++ standards. If you want to enforce strict adherence to the C++98 standard and avoid using C++11 features, you can use the -std=c++98 flag to ensure the compiler does not accept nullptr and other C++11-specific features.

Previous Page | Course Schedule | Course Content