欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

stl源码学习(版本2.91)--list

程序员文章站 2023-01-25 13:33:46
stl源码学习(版本2.91) list 一,阅读list()构造函数的收获 1,默认构造函数的作用和被调用的时机 stl_alloc.h stl_construct.h 从以上的stl list源码可以看出: list的构造函数list(),只开辟了node的内存空间,并没有构造node里的dat ......

stl源码学习(版本2.91)--list

一,阅读list()构造函数的收获

1,默认构造函数的作用和被调用的时机

struct no{
  no(int i){}
  //no(){
  //  std::cout << "s" << std::endl;
  //}
  long data;
};

struct a{
  no n;
};

int main(){
  a a;
}

这段代码报错,提示无法构造a类的a对象,编译器会给a类提供默认构造函数,但是a类的默认构造函数去构造它成员no类的n时,发现no类没有构造函数(理由:因为自己定义了no(int)构造函数,所以编译器就不提供no类的默认构造函数了),所以就无法构造n对象,也就无法构造a对象了。

知识点:

  • 如果类没有自己提供构造函数,则编译器会提供一个默认构造函数
  • 当类a里的成员里有类成员b时,当构造a时,就会去找b的构造函数,如果类b有构造函数或者默认构造函数则构造b成功。
1.cpp: in function ‘int main()’:
1.cpp:22:5: error: use of deleted function ‘a::a()’
   a a;
     ^
1.cpp:12:8: note: ‘a::a()’ is implicitly deleted because the default definition would be ill-formed:

2,allocator和定位new的用法

  • allocator:用于开辟内存空间,但是不调用构造函数
  • 定位new:不开辟内存空间,只调用构造函数

stl_list.h源码节选

template <class t>
struct __list_node {
  typedef void* void_pointer;
  void_pointer next;
  void_pointer prev;
  t data;
};

template <class t, class alloc = alloc>
class list {
protected:
  typedef __list_node<t> list_node;
  typedef simple_alloc<list_node, alloc> list_node_allocator;
public:      
  typedef list_node* link_type;

protected:
  link_type node;//list唯一的成员,是end()函数的返回值
  
public:
  list() { empty_initialize(); }
protected:
  void empty_initialize() { 
    node = get_node();
    node->next = node;
    node->prev = node;
  }
protected:
  link_type get_node() { return list_node_allocator::allocate(); }
                
  link_type create_node(const t& x) {
    link_type p = get_node();
    __stl_try {
      construct(&p->data, x);
    }
    __stl_unwind(put_node(p));
    return p;
  }
  s
  iterator insert(iterator position, const t& x) {
    link_type tmp = create_node(x);
    tmp->next = position.node;
    tmp->prev = position.node->prev;
    (link_type(position.node->prev))->next = tmp;
    position.node->prev = tmp;
    return tmp;
  }

stl_alloc.h

template<class t, class alloc>
class simple_alloc {

public:
    static t *allocate(size_t n)
                { return 0 == n? 0 : (t*) alloc::allocate(n * sizeof (t)); }
    static t *allocate(void)
                { return (t*) alloc::allocate(sizeof (t)); }

stl_construct.h

template <class t1, class t2>
inline void construct(t1* p, const t2& value) {
  new (p) t1(value);
}

从以上的stl list源码可以看出:

  • list的构造函数list(),只开辟了node的内存空间,并没有构造node里的data对象。理由:这个node的哨兵node不是list里保存数据的节点。
  • 但调用insert方法时,会调用create_node,这里面既开辟了节点的内存空间(通过调用get_node();)又调用了节点里data的构造方法(通过调用construct(&p->data, x);),然后在construct里使用了定位new(new (p) t1(value);)
  • stl里开辟空间和构造对象是分开的
  • stl里使用专用的allocator类来开辟空间

c/c++ 学习互助qq群:877684253

stl源码学习(版本2.91)--list

本人微信:xiaoshitou5854