在实现list时所遇到的问题

简介: 在实现list时所遇到的问题

问题一:临时变量具有常性问题

在list中具体的场景:

在list中,iterator迭代器被封装成了类,iterator类中有 operator!= 这一重载函数

template <class T>
  struct __list_iterator
  {
    typedef list_node<T> Node;//结点重命名为Node
    __list_iterator(Node* node)
      :_node(node)
    {}
 
    bool operator!=( __list_iterator& it)
    {
      return _node!= it._node;
    }
    Node* _node;
  };

//iterator本质上还是一个指向Node类型的指针。

调用 operator!=

  tsj::list<int> lt1;
  lt1.push_back(1);
  lt1.push_back(2);
  lt1.push_back(3);
  tsj::list<int>::iterator it = lt1.begin();
  while (it != lt1.end())
  {
    (*it) += 1;
    cout << *it << " ";
    ++it;
  }
  cout << endl;

编译器会报错,如下:

我们不是写了!=的重载函数吗?报错说不匹配,那么只可能是参数不匹配。

实参是:lt1.end() ,形参是:__list_iterator& it

end()函数如下:

  template <class T>
  class list
  {
  public:
    typedef __list_iterator<T> iterator;
    typedef list_node<T> Node;
    list()
    {
      _head = new Node;
      _head->_prev = _head;
      _head->_next = _head;
    }
  
    iterator end()
    {
      return _head->_prev;
    }
  private:
    Node* _head;
  };

函数的返回方式有两类,一类是传值返回,一类是传引用返回。这里是传值返回。

传值返回的特点是,返回值会被寄存到一个临时对象中,函数调用结束后临时对象的内容再赋值给函数调用处,且临时对象具有常性。

那么问题找到了,end()的 返回值具有常性,而形参__list_iterator& it不具有常性。因此二者的类型不匹配,所以编译器才会报如上错误。

解决方法就是在__list_iterator& it前加上const。

问题二:单参数的构造函数支持隐式类型转换  

仍然是end()函数

_head->_prev 是指针,返回类型却是iterator,很显然二者类型不同。那他为什么可以传回去呢?上述过程等价于 __list_iterator& it=_head->_prev;上文已经提到,end()是传值返回,_head->_prev 的内容被存放到一个临时对象中,然后传递给__list_iterator& it,会调用__list_iterator中的拷贝构造函数,而拷贝构造函数的形参与_head->_prev类型一致。

对这部分总结一下:单参数的构造函数支持隐式类型转换  ,形如 __list_iterator& it=_head->_prev

看似两边的类型不同,本质上是由于=右边的类型与类的成员变量类型一致,因此会发生隐式类型转换。

相关文章
|
1月前
|
Windows
该文件没有与之关联的应用来执行该操作。请安装应用,若已经安装应用,请在“默认应用设置“页面中创建关联
【10月更文挑战第22天】当你遇到“该文件没有与之关联的应用来执行该操作”的提示时,通常是因为文件类型未关联应用或文件损坏。解决方法包括:1. 确定文件类型并安装合适的应用程序,如Microsoft Office、Adobe Acrobat Reader等;2. 如果已安装应用,进入系统设置关联文件类型;3. 检查文件完整性,重新下载或验证文件格式。
1177 1
|
4月前
|
前端开发
let array = [{id:‘001‘,name:‘小新‘,age:5},{ id:‘002‘,name:‘小葵‘]这样数据如何遍历,拿到其中一个值,数组中装对象如何获取其中一个固定的值
let array = [{id:‘001‘,name:‘小新‘,age:5},{ id:‘002‘,name:‘小葵‘]这样数据如何遍历,拿到其中一个值,数组中装对象如何获取其中一个固定的值
|
6月前
四种解决”Arg list too long”参数列表过长的办法
这些方法都可以帮助你避免因参数列表过长而导致的错误。选择方法取决于具体情况和需求。
267 0
|
存储 索引
创建List保存学生信息
创建List保存学生信息
90 0
使用Stream 对List同一个id的某个字段进行计算
使用Stream 对List同一个id的某个字段进行计算
100 0
dd: 写入‘/EMPTY‘ 出错: 设备上没有空间
dd: 写入‘/EMPTY‘ 出错: 设备上没有空间
152 0
|
存储
有关list根据不同的条件,存储的对应信息数量不同
有关list根据不同的条件,存储的对应信息数量不同
65 0
SwiftUI—如何调整记录在List列表里的顺序
SwiftUI—如何调整记录在List列表里的顺序
267 0
SwiftUI—如何调整记录在List列表里的顺序
|
Java 开发者
利用 Object 类解决重复操作|学习笔记
快速学习 利用 Object 类解决重复操作
108 0