我有int* foo[SIZE]
我希望在其中搜索指向NULL
的第一个元素。
但是当我这样做时:
std::find(foo, foo + SIZE, NULL)
我收到错误:
错误C2446:'==':没有从'const int'转换为'int *'
我应该使用static_cast<int*>(NULL)
代替NULL
吗?
C ++ 11通过nullptr
解决了这个问题,但在C ++ 03中我不能选择
答案 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::begin
和std::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_ptr
或nullpointer
是不错的选择。
答案 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)
的调用
所以我们看到这个问题可以解决:
const int* piNULL = NULL
理想情况下,当使用显式强制转换时,可以避免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)
中可以实现的最紧密的内联定义。