在C ++中使用std :: allocator而不是new的优点是什么?

我刚读了std::allocator 。 在我看来,使用它而不是使用newdelete会更复杂。

使用allocator我们必须显式地分配堆内存,构造它,销毁它,然后释放内存。 那么为什么创build?

在哪些情况下可以使用,什么时候使用,而不是新的和删除?

std::allocator是标准库容器的默认内存分配器,您可以replace您自己的分配器。 这使您可以控制标准容器如何分配内存。 但是我不认为你的问题是关于std::allocator ,而是分配内存的策略,然后在内存中构造对象,而不是使用new T[N]

而原因是new T[N]不允许你控制什么构造函数被调用。 它迫使你同时构build所有的对象。 对于例如std::vector ,这只是偶尔分配的情况。

使用原始内存分配器,您可以分配一定量的内存,这决定了您的容量。 然后,当用户将项目添加到vector(使用他们select的构造函数)时,可以在此内存中构build对象。

那么当你用完内存,你分配更多,通常两倍。 如果std::vector使用了new T[N] ,那么每次需要添加或删除一个元素时都必须重新分配,这对于性能来说是非常糟糕的。 你也将被迫使用所有对象的默认构造函数,这就对std::vector可以容纳的对象的types进行了不必要的限制。

在我看来,使用它而不是使用new和delete会更复杂。

是的,但并不意味着取代newdelete ,它服务于不同的目的。

使用分配器,我们必须显式地分配堆内存,构造它,销毁它,然后释放内存。

那么为什么创build?

因为有时候你想把分配和build设分成两个步骤(类似的是把分解和分配分成两步)。 如果你不想这样做,不要使用分配器,而是使用new

在哪些情况下可以使用,什么时候使用,而不是新的和删除?

当你需要一个分配器的行为,而不是newdelete的行为,显然! 典型的情况是在执行一个容器时。

考虑下面的代码:

 std::vector<X> v; v.reserve(4); // (1) v.push_back( X{} ); // (2) v.push_back( X{} ); // (3) v.clear(); // (4) 

这里行(1)必须为四个对象分配足够的内存,但是不能构造它们。 然后行(2)和(3)必须构build对象到分配的内存中。 然后第(4)行必须销毁这些对象,但不能释放内存。 最后,在vector的析构函数中,所有的内存都可以被释放。

所以向量不能只使用new X()或者delete &m_data[1]来创build和销毁对象,它必须执行与构造/销毁分开的分配/解除分配。 一个容器的分配器模板参数定义了应该用于(de)分配内存和构造/析构对象的策略,允许容器对内存的使用进行自定义。 默认策略是std::allocatortypes。

所以当你需要一个分配器的时候(比如使用一个容器的时候),你使用了一个std::allocator当你不想提供一个自定义的分配器而只需要一个标准的std::allocator时候就使用了std::allocator

您不使用分配器来replacenewdelete

分配器是STL中一个非常重要的概念。 每个容器都可以将分配器作为参数。 然后分配将使用这个分配器来执行,而不是标准分配器。

这对于例如在池中分配相同大小的对象来提高性能是有用的,或者如果存在对象需要存储的特殊区域,则这可能是必要的。

分配和构造的步骤是分开的,因为例如对于vector( std::vector::reserve ),能够分配内存以备将来使用是非常重要的,但不能在其中创build对象。

作为一个例子,你可以写一个分配器作为一个类,包含一个固定大小的数组,并使用该数组为一些标准容器提供内存。 然后,你可以在堆栈上有一个这样的类的实例,从而完全避免了程序的某些部分的堆分配。

在这个SOpost里看到更多的例子。

何时使用[…]

当你有特定的需求时,最重要的是编写自己的通用容器。

你的直觉是对的。 在90%的情况下,使用new 。 但是,注意结构,比如地图数据结构。 它的默认模板参数之一是class Alloc = allocator<pair<const Key,T> ,它定义了类如何创build事物的新实例并pipe理现有实例。 通过这种方式,理论上可以创build自己的分配器,然后将其用于现有的数据结构。 因为newdelete是函数而不是类,所以有必要让std::allocator来表示它们并使它们成为有效的模板参数。

std::allocator被创build为允许开发人员更多地控制如何分配内存。 在许多embedded式系统中,内存受到限制,而且types也不同。 可能不是很多。 此外,内存分配希望被最小化,以避免碎片问题。

分配器还允许从不同的内存池分配。 因此,例如,从小块存储池中分配小尺寸块将会更有效率。

newdelete是在dynamic内存中创build一个对象并直接初始化它的直接方法。 分配者更多,因为他们提供了完全控制上述阶段。

使用分配器,我们必须显式地分配堆内存,构造它,销毁它,然后释放内存。

实际上,分配器不应该被用于“正常”的代码, newdelete同样可以。 考虑一个像std::map这样的类,经常以树的forms实现:当一个对象被删除时,是否需要释放整个叶子? 分配器允许你破坏这个对象,但是保留这个内存,这样你就不必再需要它了。

此外,如果你知道更多的控制优化方法,那么你可以专门化一个特定types的分配器,这对于newdelete是不可能的。

这个STL成员的原因是为了让开发人员更好地控制内存。 我的意思是说,新运营商本身并不只是一种运营方式。 在最基本的情况下,它执行内存预留,然后用对象填充该空间。

尽pipe我无法想出一个特定的真实世界的案例场景,但是也许应该使用std::allocator ,例如,销毁给定的对象可能会影响内存中的其他对象。

比方说,为了论证,你创build了某种向量,每个元素都与内存中的其他对象双向链接,并且在删除所述向量的时候,要将链接的对象删除引用返回到它。