写点什么

C++ 学习 ---STL 中 nullptr_t 的实现原理

作者:桑榆
  • 2022 年 9 月 15 日
    广东
  • 本文字数:1771 字

    阅读完需:约 6 分钟

引言

nullptr_t/nullptr 是对 C 语言中 NULL 的替代,C 语言中 NULL 通常定义为 0 或(void*)0,无法很好地处理与 C++相关的环境,比如类指针的转换、赋值、比较等,容易出现异常。我们来分析一下 C++STL 中是如何定义 nullptr 的,学习 STL 相关的编程技法。

nullptr_t 的定义与实现

代码参考:http://www.aospxref.com/android-13.0.0_r3/xref/external/libcxx/include/__nullptr

源码展示

22 _LIBCPP_BEGIN_NAMESPACE_STD23 24 struct _LIBCPP_TEMPLATE_VIS nullptr_t25 {26     void* __lx;27 28     struct __nat {int __for_bool_;};29 30     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t() : __lx(0) {}31     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t(int __nat::*) : __lx(0) {}32 33     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator int __nat::*() const {return 0;}34 35     template <class _Tp>36         _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR37         operator _Tp* () const {return 0;}38 39     template <class _Tp, class _Up>40         _LIBCPP_INLINE_VISIBILITY41         operator _Tp _Up::* () const {return 0;}42 43     friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator==(nullptr_t, nullptr_t) {return true;}44     friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator!=(nullptr_t, nullptr_t) {return false;}45 };46 47 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t __get_nullptr_t() {return nullptr_t(0);}48 49 #define nullptr _VSTD::__get_nullptr_t()50 51 _LIBCPP_END_NAMESPACE_STD
复制代码

成员变量---void* __lx

可以看到,实际上 nullptr_t 的实现还是使用了 void*指针,其中void* __lx就是真正表示的空指针;又增加了结构体__nat 定义,里面只有一个 int 型变量。

成员函数

默认构造函数

实际上直接将__lx 初始化为 0,这一点与 C 语言的处理是一致的。

_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t() : __lx(0) {}
复制代码

转换构造函数---将 int 型转换为 nullptr_t

实现上还是将__lx 初始化为 0,只是这里用到了结构体成员指针的概念,int __nat::*这里实际上指代的是 struct __nat 中的成员变量,因为后文中并未用到该变量,所以没有填写入参名,完整的参数应该是int __nat::*nm,nm 表示__nat 中任意一个成员变量,具体由传参时决定,这里都是 int 型。

_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t(int __nat::*) : __lx(0) {}
复制代码

类型转换函数---nullptr_t 转换为 int 型

即空指针 nullptr 转换为 int 型得到 0。

_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator int __nat::*() const {return 0;}
复制代码

类型转换函数---nullptr_t 转换为_Tp*

这里利用模板定义,将 nullptr_t 转换为任意指针类型,实际上是返回 0 指针。

template <class _Tp>_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR    operator _Tp* () const {return 0;}
复制代码

类型转换函数---nullptr_t 转换为_Tp _Up::*

这个是考虑到类成员指针的情况,将 bullptr_t 转换为任意类中的任意类型,实际上是返回 0 指针。

template <class _Tp, class _Up>_LIBCPP_INLINE_VISIBILITY    operator _Tp _Up::* () const {return 0;}
复制代码

比较函数

定义为 nullptr_t 的友元函数,判断两个 nullptr_t 是否相等,是否不等,逻辑也比较简单。

friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator==(nullptr_t, nullptr_t) {return true;}friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator!=(nullptr_t, nullptr_t) {return false;}
复制代码

定义 nullptr

实际上我们使用的是 nullptr,他是 nullptr_t 的一个实例,该实例实际上就是使用 nullptr_t(0)进行初始化的。

47 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t __get_nullptr_t() {return nullptr_t(0);}48 49 #define nullptr _VSTD::__get_nullptr_t()
复制代码

总结

STL 中对 nullptr_t 进行了定义,对 int 转 nullptr_t,nullptr_t 转其它指针类型做了准确说明,本质上还是使用(void*)0 的方式,但是更加符合 C++规范,也避免了隐式转换,保证空指针的行为是可控的,不能够随意参加算数运算,相比起(void*)0 的方式更加安全,因此,在 C++中,也建议使用 nullptr 代替 NULL 表示空指针。

发布于: 2022 年 09 月 15 日阅读数: 43
用户头像

桑榆

关注

北海虽赊,扶摇可接;东隅已逝,桑榆非晚! 2020.02.29 加入

Android手机厂商-相机软件系统工程师 爬山/徒步/Coding

评论

发布
暂无评论
C++学习---STL中nullptr_t的实现原理_c++_桑榆_InfoQ写作社区