查找指向 NULL 的指针

Finding a Pointer to NULL

我有 int* foo[SIZE],我想在其中搜索指向 NULL 的第一个元素。

但是当我这样做时:

 std::find(foo, foo + SIZE, NULL)

我收到错误:

error C2446: '==' : no conversion from 'const int' to 'int *'

我应该只使用 static_cast<int*>(NULL) 而不是 NULL 吗?

C++11 通过 nullptr 解决了这个问题,但在 C++03

中这不是我的选择

tl;dr:使用 nullptr,或定义您自己的等价物。


问题是 NULL 是一些扩展为值为零的整型常量表达式的宏。为了调用该函数,std::find 必须推导类型并使用值 (0)。

您不能将 int*int 进行比较,因此会出现错误。就函数而言,您只是向它传递了一些恰好为零的常规旧 int,并且这些不能转换为空指针;它们必须是整数常量表达式。

通常 NULL "works" 因为它在不被视为整数形式的上下文中使用,例如:

if (ptr == NULL)

因为这里保持"integral constant expression"状态,所以转换为比较类型的空指针。

如果您使用的是 C++11 或更高版本,则应使用 nullptr,因为这实际上是一个空指针,而不是转换为它的整数。您所描述的实际上是引入 nullptr.

的激励因素之一

如果您需要,nullptr 有多种 C++03 实现。我在这个答案的底部附加了 classic 实现。

此外,如果可能,您应该更喜欢 std::array(如果需要,Boost 有一个),或者至少使用 std::beginstd::end 来获取数组开始和结束指针(同样,有这个浮动的实现):

#include <algorithm>
#include <array>

int main() {
    std::array<int*, 8> foo = {};
    std::find(foo.begin(), foo.end(), nullptr);
}

总而言之,在紧要关头强制转换为您的类型的空指针是一个有效的解决方案。 nullptr 实际上只是 "a thing that converts to the null pointer of the needed type".

的缩写

这是一个 nullptr 实现,最初由 Scott Meyers 创建:

const
struct nullptr_t {
    template <typename T>
    operator T*() const {
        return 0;
    }

    template <typename C, typename T>
    operator T C::*() const {
        return 0;
    }

  private:
    void operator&() const;

} nullptr = {};

语法看起来有点滑稽,因为我们通常不会同时定义 class 和变量。显然,如果你想保持 C++11 兼容,nullptr 不是可用的标识符。 null_ptrnullpointer 是不错的选择。

这个问题实际上在 Herb Sutter 和 Bjarne Stroustrup 中被指出:A name for the null pointer: nullptr:

Distinguishing between null and zero. The null pointer and an integer 0 cannot be distinguished well for overload resolution. For example, given two overloaded functions f(int) and f(char*), the call f(0) unambiguously resolves to f(int). There is no way to write a call to f(char*) with a null pointer value without writing an explicit cast (i.e., f((char*)0)) or using a named variable

所以我们看到这个问题可以通过以下任一方式解决:

  1. 显式转换
  2. 类型匹配的值的声明,例如:const int* piNULL = NULL

理想情况下,当使用显式强制转换时,可以避免 C 风格强制转换。这些 C++ 样式中的任何一个都有效地转换 returns 包含地址 NULL:

int*
  • reinterpret_cast<int*>(NULL)
  • static_cast<int*>(NULL)

http://en.cppreference.com/w/cpp/types/NULL 断言:

A null pointer constant may be implicitly converted to any pointer type; such conversion results in the null pointer value of that type

并且由于 static_cast:

Converts between types using a combination of implicit and user-defined conversions

static_castreinterpret_cast 更准确地定义了预期的转换类型:

Converts between types by reinterpreting the underlying bit pattern

因此,在 C++03 中 static_cast<int*>(NULL) 是 C++11 的 nullptr 中可以实现的最严格的内联定义.