# nullptr 与初始化列表

URL: https://caijiao.org/cpp/stl/nullptr-init
Source: docs/cpp/stl/nullptr-init.md
Description: 本节介绍 C++ 中的 'nullptr' 和初始化列表的概念及用法，帮助更好地理解现代 C++ 中的内存管理与对象初始化方式。

## nullptr

`nullptr` 是 C++11 引入的关键字，代表一个空指针常量。它提供了比 `NULL` 更加类型安全的方式来表示空指针。

### 为什么使用 `nullptr`？

在 C++ 中，传统的空指针常量 `NULL` 是宏定义，通常被定义为 `0` 或 `(void*)0`。这会导致在函数重载时产生歧义。`nullptr` 则是一个类型安全的指针常量，可以避免这种歧义。

### 示例：使用 `nullptr`

```cpp
#include <iostream>

void func(int* ptr) {
    if (ptr == nullptr) {
        std::cout << "Pointer is null!" << std::endl;
    } else {
        std::cout << "Pointer is not null!" << std::endl;
    }
}

int main() {
    int* p = nullptr;  // 使用 nullptr 初始化指针
    func(p);  // 输出 Pointer is null!

    return 0;
}
````

在此示例中，`p` 被初始化为 `nullptr`，确保它是一个空指针。

## 初始化列表

初始化列表是一种在构造函数中为成员变量提供初始值的机制。在 C++ 中，使用初始化列表比在构造函数体内赋值更高效。

### 为什么使用初始化列表？

1. **性能优化**：初始化列表直接为成员变量赋初值，而不是先调用默认构造函数再赋值。
2. **对常量和引用的初始化**：常量成员和引用成员必须通过初始化列表进行初始化。
3. **避免不必要的赋值**：某些类型（如 `std::vector`）可能会在构造函数体内进行内存分配，使用初始化列表可以避免重复分配内存。

### 示例：使用初始化列表

```cpp
#include <iostream>

class MyClass {
private:
    int x;
    const int y;
    double z;

public:
    // 使用初始化列表初始化成员变量
    MyClass(int a, int b, double c) : x(a), y(b), z(c) {}

    void print() {
        std::cout << "x = " << x << ", y = " << y << ", z = " << z << std::endl;
    }
};

int main() {
    MyClass obj(10, 20, 30.5);
    obj.print();  // 输出 x = 10, y = 20, z = 30.5

    return 0;
}
```

在此示例中，`x` 和 `z` 使用初始化列表进行初始化，而 `y` 是一个常量，必须通过初始化列表初始化。

### 常见错误

1. **忘记使用初始化列表初始化常量和引用成员**：

   ```cpp
   class MyClass {
   private:
       const int x;

   public:
       MyClass() {
           // 错误：无法在构造函数体内为常量成员初始化
           x = 10;  
       }
   };
   ```

2. **使用初始化列表进行成员初始化时未初始化所有成员**：

   ```cpp
   class MyClass {
   private:
       int x;
       double y;

   public:
       // 错误：没有初始化 y
       MyClass(int a) : x(a) {}
   };
   ```

   这种情况下，编译器可能会警告你有未初始化的成员变量。

## 总结

* `nullptr` 是 C++11 引入的空指针常量，提供了比 `NULL` 更加类型安全的方式来表示空指针。
* 初始化列表提供了更高效、更安全的成员初始化方式，尤其在需要初始化常量和引用时必不可少。
* 使用初始化列表时应确保初始化所有成员变量，避免遗漏。

通过 `nullptr` 和初始化列表，C++ 提供了更为现代的内存管理与对象初始化方式，有助于编写更高效和安全的代码。
