引子
这一条目就比较简单了,就是宣传用nullptr来指代空指针,而不是之前的0或者NULL。
正文
在老式C++中,显然0是int类型,而NULL也是一个整数类型(int或者long)。总的来说,这两个常用来表示空指针的符号并不是真正的指针类型。这样,当我们在进行函数重载时会发生麻烦,例如:
void f(int); // three overloads of f
void f(bool);
void f(void*);
f(0); // calls f(int), not f(void*)
f(NULL); // might not compile, but typically calls f(int). Never calls f(void*)
所以在C++98中,一些准则教育程序员不要同时重载int和指针类型。但在C++11中,移除了这个限制,因为我们有一个新的关键字nullptr来代表空指针。
但是,准确的说,nullptr也不是空指针类型而是std::nullptr_t类型。这里有点循环定义的意思在里面,因为std::nullptr_t类型就是nullptr的类型。
此时我们再调用f(nullptr)时就准确地调用了f(void*)而不是其他重载函数。因为nullptr不会被转换为基本类型。
不过虽然0可以被看作空指针,但是并不是int类型会被隐式转换为空指针,例如:
void test(void*);
int data = 0;
test(0); //Ok, but not recommanded
test(data); //Error, could not convert from "int" to "void*"
了解了上面的机制,你就很容易看懂最后这个模板的例子:
using MuxGuard = std::lock_guard<std::mutex>;
template<typename FuncType,
typename MuxType,
typename PtrType>
decltype(auto) lockAndCall(FuncType func,
MuxType& mutex,
PtrType ptr
{
MuxGuard g(mutex);
return func(ptr);
}
int f1(std::shared_ptr<Widget> spw); // call these only when
double f2(std::unique_ptr<Widget> upw); // the appropriate
bool f3(Widget* pw); // mutex is loc
std::mutex f1m, f2m, f3m; // mutexes for f1, f2, and f3
auto result1 = lockAndCall(f1, f1m, 0); // error!
auto result2 = lockAndCall(f2, f2m, NULL); // error!
auto result3 = lockAndCall(f3, f3m, nullptr); // fine
上面前两次调用都失败了,这是由于0和NULL都被推导为整数类型,并进一步传递个内部的函数func(这里是f1和f2)。而整数类型无法被转换为指针类型,故代码错误。
总结
综上,我们有:
1.用
nullptr代替0和NULL来指示空指针。
2.不要同时重载参数为整数类型和指针类型的函数。
本文探讨了C++11中引入的新关键字nullptr,解释了它如何替代传统的0和NULL来表示空指针。通过示例说明了使用nullptr能够避免函数重载时的类型匹配问题,并强调了其在模板函数中的正确使用方式。
1363

被折叠的 条评论
为什么被折叠?



