0 结论
避免在整型和指针类型间重载,尽量使用nullptr代替空指针。
1 nullptr、NULL和0
一般情况下,人们经常习惯于使用0或NULL来代指空指针,这容易导致歧义或者程序编译错误。例如:
下面的代码中,f(NULL)会导致歧义,使得编译器不知道调用哪个函数。
using std::cout; using std::endl;
void f(void*){
cout<<"f(void*)"<<endl;
}
void f(int){
cout<<"f(int)"<<endl;
}
int main(){
f(0);
// f(NULL);//error: call to 'f' is ambiguous
f(nullptr);
return 0;
}
在使用模版类型推导时,模版只会把NULL和0推导为整数,而不会是空指针,例如:
下面代码result1和2都会报错。
using std::cout; using std::endl;
class Widget{
};
int f1(std::shared_ptr<Widget> spw){ return 1;};
double f2(std::unique_ptr<Widget> upw){ return 1.0;};
bool f3(Widget* pw){ return true;}
std::mutex f1m, f2m, f3m;
using MuxGuard = std::lock_guard<std::mutex>;
template <typename FunType,
typename MuType,
typename PtrType>
//auto lockAndCall(FunType func, //C++11
// MuType& mutex,
// PtrType ptr)-> decltype(func(ptr)){//类型还可以写成 decltype(auto)
decltype(auto) lockAndCall(FunType func, //c++14
MuType& mutex,
PtrType ptr){//类型还可以写成 decltype(auto)
MuxGuard g(std::mutex);
return func(ptr);
}
int main(){
//auto result1 = lockAndCall(f1, f2, 0);//error: no matching function for call to 'lockAndCall'
//auto result2 = lockAndCall(f1, f2, NULL);//error: no matching function for call to 'lockAndCall'
auto result3 = lockAndCall(f1, f2, nullptr);
return 0;
}
注意⚠️:
nullptr的类型为std::nullptr_t
。(其源代码为:namespace std { typedef decltype(nullptr) nullptr_t; }
)
检验代码为:
using std::cout; using std::endl;
void f(void*){
cout<<"f(void*)";
}
int main(){
std::nullptr_t null;
// f(NULL);//error: call to 'f' is ambiguous
f(null);
return 0;
}