# nullptr

nullptr 是用来调换 NULL 的

在 C 中 NULL 用于指针中一般是 (void *),用于整型是 0
这导致在重载时指针类型和整型会有歧义

如下例子中可以体现这一点

#include <iostream>
#include <type_traits>

void foo(char *);
void foo(int);

int main() {
  if (std::is_same<decltype(NULL), decltype(0)>::value) {
    std::cout << "NULL == 0" << std::endl;
  }
  if (std::is_same<decltype(NULL), decltype((void *)0)>::value) {
    std::cout << "NULL == (void *)0" << std::endl;
  }
  if (std::is_same<decltype(NULL), decltype(nullptr)>::value) {
    std::cout << "NULL == nullptr" << std::endl;
  }

  foo(0);
  foo(NULL);
  foo(nullptr);

  return 0;
}


void foo(char *) {
  std::cout << "foo(char *) is called" << std::endl;
}

void foo(int) {
  std::cout << "foo(int) is called" << std::endl;
}
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
31
32

输出

NULL == 0
foo(int) is called
foo(int) is called
foo(char *) is called
1
2
3
4

可以看到这里 NULL 按照整型来处理的,而 nullptr 可以精确的认为是空指针

实际上 nullptr 是一个关键词,如果取类型的话,是 std::nullptr_t

疑问:是否和定义顺序有关系?
交换 foo 的定义和实现的顺序,执行结果不变,说明和定义顺序无必然联系


# decltype

例子中出现的 decltype 操作符需要说明下,不可以简单理解为函数,实际上它的结果是类型,类似于 int, float

维基百科中说的很清晰

虽然C++规范或大多数的文档及书籍都将decltype定义为一个操作符,但是针对初学者而言,应将此操作符理解为一种特殊的类型声明,而不是像一些强类型语言那样将此操作符理解为一个带返回值的函数。 举例:设开发人员无法确定一个表达式exp()的值类型,然而需要声明一个与之类型匹配的变量,则可以如下声明: decltype(exp()) x;

#include <iostream>

int add(int a, int b) {
  return a + b;
}

int main() {
  decltype(add(1, 2)) x = add(2, 3);
  std::cout << x << std::endl;
  return 0;
}
1
2
3
4
5
6
7
8
9
10
11

输出

5
1

参考资料