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

Why does std::vector use std::allocator instead of operator new and delete?

本文关键字:std new 运算符 delete vector 使用 分配器 为什么      更新时间:2023-10-16

>我正在阅读该语言作者的"使用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;
}
};

如果我使用 new 和 delete 会出什么问题?

T* p = new T[newallow];

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

分配器的基本思想是将分配内存和对象构造的步骤分开。默认new将两者结合起来。在vector保留的情况下,我们只想分配所需的内存。当时我们无法构造或初始化对象,因为该类型可能不是默认可构造的。只有当我们在其他操作中传递要存储的对象时,才能在以后构造对象,例如

v[i] = myObj;

如果不在两个不同的步骤中分离内存分配和对象构造,就无法实现这一点。

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

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

作者的意思是,在通过调用reserve来增加容量的同时,我们将拥有两种类型的数据:

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