为什么std :: vector使用std :: allocator而不是new和delete运算符?

时间:2018-09-21 04:32:29

标签: c++

我正在阅读该语言作者的书《使用C ++的编程原理和实践》。

我正在阅读本书的基本部分,其中描述了如何实现std :: vector。这是本书中的一段代码:

template<typename T, typename A = std::allocator<T>> class vector {
    A alloc;
    int space, size;
    T* elem;
    //...some code
    reserve(int newalloc) {
        if (newalloc <= space) return;               // never decrease allocation       
        T* p =  alloc.allocate(newalloc);          // allocate new space          
        for (int i = 0; i < sz; ++i) alloc.construct(&p[i], elem[i]);       // copy         
        for (int i = 0; i < sz; ++i) alloc.destroy(&elem[i]);                 // destroy         
        alloc.deallocate(elem, space);             // deallocate old space         
        elem = p;
        space = newalloc;
    }
};

这本书提到我们必须使用std :: allocator,因为向量的数据结构由一些初始化数据和一些未初始化数据组成。

我不清楚这意味着什么。如果我使用new和delete怎么办?

template<typename T> class vector2 {
    A alloc;
    int space, size;
    T* elem;
    //some code
    reserve(int newalloc) {
        if (newalloc <= space) return;                     
        T* p = new T[newallow];      
        for (int i = 0; i < sz; ++i) p[i] = elem[i];
        delete[] elem;                 
        elem = p;
        space = newalloc;
    }
};

1 个答案:

答案 0 :(得分:13)

  

如果我使用new和delete怎么办?

T* p = new T[newallow];

一个原因是,如果T没有默认构造函数,则不会编译。

分配器的基本思想是将分配内存和对象构造的步骤分开。默认new结合了两者。如果预留vector,我们只想分配所需的内存。当时我们无法构造或初始化对象,因为类型可能不是默认可构造的。仅当我们将对象传递给其他操作(例如

)进行存储时,才能稍后构造对象
v[i] = myObj;

如果不将内存分配和对象构造分为两个不同的步骤,就无法实现。

还请注意,当有人要自定义内存分配时,分配器具有高级用法。

  

这本书提到我们必须使用std :: allocator,因为向量的数据结构包含一些初始化数据和一些未初始化数据。

作者在这里的意思是,通过调用reserve扩展容量的同时,我们将获得两种类型的数据:

  1. 向量中需要移动到新空间的现有对象。它们是初始化数据。
  2. 额外的保留空间,该空间尚未存储任何对象,因此未初始化。