设为首页 加入收藏

TOP

【whale-starry-stl】01天 list学习笔记(一)
2023-07-23 13:26:31 】 浏览:111
Tags:whale-starry-stl list 习笔记

一、知识点

1. std::bidirectional_iterator_tag

std::bidirectional_iterator_tagC++ 标准库中定义的一个迭代器类型标签,用于标识支持双向遍历的迭代器类型。

C++ 中,迭代器是一种泛型指针,用于遍历容器中的元素。迭代器类型标签用于标识迭代器的特性,从而在算法中选择合适的迭代器类型。

std::bidirectional_iterator_tag 是迭代器类型标签中的一种,用于标识支持双向遍历的迭代器类型。双向迭代器可以向前和向后遍历容器中的元素,支持 ++-- 运算符。

标准库中的许多算法都要求迭代器支持特定的操作,例如 std::reverse 要求迭代器支持双向遍历,因此可以使用 std::bidirectional_iterator_tag 标签来限定迭代器的类型,从而保证算法的正确性。

//迭代器类型标签,用于标识支持双向遍历的迭代器类型,支持++和--运算符
typedef std::bidirectional_iterator_tag    iterator_category;

2. ptrdiff_t

ptrdiff_t 是 C++ 标准库中定义的一个整型类型,用于表示指针之间的差值(即两个指针在内存中的地址差距)。在 C++ 中,指针的加减运算结果是一个 ptrdiff_t 类型的值。

ptrdiff_t 的实现是平台相关的,通常是一个带符号的整数类型。在 32 位平台上,ptrdiff_t 通常是一个 4 字节的整型,而在 64 位平台上,ptrdiff_t 通常是一个 8 字节的整型。

使用 ptrdiff_t 类型可以保证指针操作的安全性,因为指针之间的差值可能超出普通整型的表示范围。此外,使用 ptrdiff_t 类型还可以提高代码的可移植性,因为不同平台上指针的大小可能不同。

//带符号整型,表示指针之间的差值(即两个指针在内存中的地址差距)
typedef ptrdiff_t                          difference_type;

3. #if __cplusplus >= 201103L

#if __cplusplus >= 201103L这行代码是C++中的条件编译指令,意思是如果当前编译器支持C++11标准或更高版本,则编译下面的代码。其中,__cplusplus是一个C++预定义宏,表示当前编译器所支持的C++标准版本,201103L表示C++11标准的版本号。因此,这行代码的作用是在编译时检查当前编译器是否支持C++11标准或更高版本,如果支持,则编译下面的代码,否则忽略。

4. explicit

explicit 是 C++ 中的一个关键字,用于修饰类的构造函数,表示该构造函数是显式的,不能进行隐式转换。

在 C++ 中,如果一个类的构造函数只有一个参数,那么这个构造函数可以被用于隐式转换。例如,如果有一个类 A 和一个构造函数 A(int),那么可以使用 A a = 1; 的方式创建一个 A 类型的对象,这里的 1 会被自动转换为 A 类型。

使用 explicit 关键字可以禁止这种隐式转换,从而避免一些潜在的问题。例如,如果一个类 B 有一个构造函数 B(int),但是我们希望这个构造函数只能显式调用,那么可以将其声明为 explicit,这样就不能再使用 B b = 1; 的方式创建一个 B 类型的对象,而必须显式地调用 B b(1);

另外,explicit 关键字还可以用于修饰转换函数,表示该函数也是显式的,不能进行隐式转换。

5. stl_list.h结构

6. 迭代器相关

  • 运算符重载
    重载++(分为++item与item++)

    重载*&

7. 迭代器 traits

  • 模板偏特化(感觉类似java泛型重载)
    image-20230619210901175

  • 完整的iterator_traits
    image-20230619210958775

二、源码

_List_node_base

主要提供了prev和next指针,以及一些方法。

struct _List_node_base
{
      _List_node_base* _M_next;
      _List_node_base* _M_prev;
      ...
};

_List_node

继承自_List_node_base,主要提供了一个存放数据的 _M_data

/// An actual node in the %list.
  template<typename _Tp>
    struct _List_node : public __detail::_List_node_base
    {
      ///< User's data.
      _Tp _M_data;
//检查编译器是否支持c++11及以上版本
#if __cplusplus >= 201103L
      template<typename... _Args>
        _List_node(_Args&&... __args)     //万能引用
	: __detail::_List_node_base(), _M_data(std::forward<_Args>(__args)...) //完美转发
        { }
#endif
    };

_List_iterator

迭代器

1. 必须定义的五个typedef

      //下面这五个typedef是每个iterator必须有的
      //带符号整型,表示指针之间的差值(即两个指针在内存中的地址差距)
      typedef ptrdiff_t                          difference_type;
      //迭代器类型标签,用于标识支持双向遍历的迭代器类型,支持++和--运算符
      typedef std::bidirectional_iterator_tag    iterator_category;
      typedef _Tp                                value_type;
      typedef _Tp*                               pointer;
      typedef _Tp&                               reference;

2. 两个构造器

      _List_iterator() _GLIBCXX_NOEXCEPT
      : _M_node() { }

      explicit //修饰类的构造函数,表示该构造函数是显式的,不能进行隐式转换
      _List_iterator(__detail::_List_node_base* __x) _GLIBCXX_NOEXCEPT
      : _M_node(__x) { }      //_M_node:_List_node_base

3. 运算符重载

个人理解,此处之所以能够向下造型,应该是传入参数的时候已经做过一次向上造型

// Must downcast from _List_node_base to _List_node to get to _M_data.
      reference
      operator*() const _GLIBCXX_NOEXCEPT 
      { return static_cast<_Node*>(_M_node)->_M_data; }     //_M_node:_List_node_base, _Node:_List_node<_Tp>

      pointer
      operator->() const _GLIBCXX_NOEXCEPT      //2.9版本中是return &(operator*())
      { return std::__addressof(static_cast<_Node*>(_M_node)->_M_data); }      //__addressof用于取地址

首页 上一页 1 2 3 4 5 下一页 尾页 1/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C++面试八股文:什么是智能指针? 下一篇驱动开发:应用DeviceIoContro模..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目