在实现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

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

相关文章
|
6月前
|
Java
初始化ArrayList的方式
初始化ArrayList的方式
52 4
|
6月前
四种解决”Arg list too long”参数列表过长的办法
这些方法都可以帮助你避免因参数列表过长而导致的错误。选择方法取决于具体情况和需求。
248 0
|
6月前
|
前端开发 Java 测试技术
把List<对象>转变<String,List<对象>>形式,k为判断的值,v为k重复的数据。
把List<对象>转变<String,List<对象>>形式,k为判断的值,v为k重复的数据。
36 0
|
XML 前端开发 数据格式
当返回前端的数据中存在List对象集合,如何优雅操作?
当返回前端的数据中存在List对象集合,如何优雅操作?一对多结构简单不冗余,便于前端取数据,是一个好的解决方案。
196 0
|
存储 索引
创建List保存学生信息
创建List保存学生信息
90 0
使用Stream 对List同一个id的某个字段进行计算
使用Stream 对List同一个id的某个字段进行计算
98 0
C++ -- list类模拟实现
C++ – list类模拟实现 0. list类成员变量和节点
84 0
|
C++
C++中,类如果包含map/list等对象,慎用memset(0)
C++中,类如果包含map/list等对象,慎用memset(0)
117 0
Python: list of list, 将内部 list 的 index 作为该内部 list 中每个元素的分类标签
Python: list of list, 将内部 list 的 index 作为该内部 list 中每个元素的分类标签
|
Java
List Stream 的常规用法
List Stream 的常规用法
114 0