查找指针为NULL

时间:2016-10-13 21:37:10

标签: c++ casting null c++03 nullptr

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

但是当我这样做时:

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

我收到错误:

  

错误C2446:'==':没有从'const int'转换为'int *'

我应该使用static_cast<int*>(NULL)代替NULL吗?

C ++ 11通过nullptr解决了这个问题,但在C ++ 03中我不能选择

2 个答案:

答案 0 :(得分:6)

tl; dr:使用nullptr,或定义自己的等效项。

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

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

通常NULL&#34;工作&#34;因为它在上下文中使用,它不被视为整数形式,例如:

if (ptr == NULL)

因为在这里它保持了它的&#34;积分常数表达式&#34; status,因此转换为compare-to类型的空指针。

如果你在C ++ 11或更高版本中,你应该使用nullptr,因为这实际上是一个空指针,而不是一个转换为它的整数。你所描述的实际上是引入nullptr的推动因素之一。

如果需要,nullptr有各种C ++ 03实现。我在这个答案的底部附上了经典的实现。

另外,如果可能的话,你应该更喜欢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实际上只是简单地转换为所需类型的空指针&#34;。

这是一个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 = {};

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

答案 1 :(得分:0)

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

  

区分null和零。对于重载决策,无法很好地区分空指针和整数0。例如,给定两个重载函数f(int)f(char*),调用f(0)明确地解析为f(int)。没有编写显式强制转换(即f(char*))或使用命名变量

,无法使用空指针值写入f((char*)0)的调用

所以我们看到这个问题可以解决:

  1. 明确的演员
  2. 声明具有匹配类型的值,例如:const int* piNULL = NULL
  3. 理想情况下,当使用显式强制转换时,可以避免C样式强制转换。这些C ++中的任何一个 - 样式转换有效地返回包含地址int*的{​​{1}}:

    • NULL
    • reinterpret_cast<int*>(NULL)

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

      

    空指针常量可以隐式转换为任何指针类型;这种转换会导致该类型的空指针值

    static_cast开始:

      

    使用隐式转换和用户定义转换的组合在类型之间进行转换

    static_cast<int*>(NULL)reinterpret_cast更接近地定义了投射的类型:

      

    通过重新解释基础位模式

    在类型之间进行转换

    因此,C ++ 03中的 static_cast是C ++ 11 static_cast<int*>(NULL)中可以实现的最紧密的内联定义