在C ++中使用std :: allocator而不是new的优点是什么?
我刚读了std::allocator
。 在我看来,使用它而不是使用new
和delete
会更复杂。
使用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会更复杂。
是的,但并不意味着取代new
和delete
,它服务于不同的目的。
使用分配器,我们必须显式地分配堆内存,构造它,销毁它,然后释放内存。
那么为什么创build?
因为有时候你想把分配和build设分成两个步骤(类似的是把分解和分配分成两步)。 如果你不想这样做,不要使用分配器,而是使用new
。
在哪些情况下可以使用,什么时候使用,而不是新的和删除?
当你需要一个分配器的行为,而不是new
和delete
的行为,显然! 典型的情况是在执行一个容器时。
考虑下面的代码:
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::allocator
types。
所以当你需要一个分配器的时候(比如使用一个容器的时候),你使用了一个std::allocator
当你不想提供一个自定义的分配器而只需要一个标准的std::allocator
时候就使用了std::allocator
。
您不使用分配器来replacenew
和delete
。
分配器是STL中一个非常重要的概念。 每个容器都可以将分配器作为参数。 然后分配将使用这个分配器来执行,而不是标准分配器。
这对于例如在池中分配相同大小的对象来提高性能是有用的,或者如果存在对象需要存储的特殊区域,则这可能是必要的。
分配和构造的步骤是分开的,因为例如对于vector( std::vector::reserve
),能够分配内存以备将来使用是非常重要的,但不能在其中创build对象。
作为一个例子,你可以写一个分配器作为一个类,包含一个固定大小的数组,并使用该数组为一些标准容器提供内存。 然后,你可以在堆栈上有一个这样的类的实例,从而完全避免了程序的某些部分的堆分配。
在这个SOpost里看到更多的例子。
何时使用[…]
当你有特定的需求时,最重要的是编写自己的通用容器。
你的直觉是对的。 在90%的情况下,使用new
。 但是,注意结构,比如地图数据结构。 它的默认模板参数之一是class Alloc = allocator<pair<const Key,T>
,它定义了类如何创build事物的新实例并pipe理现有实例。 通过这种方式,理论上可以创build自己的分配器,然后将其用于现有的数据结构。 因为new
和delete
是函数而不是类,所以有必要让std::allocator
来表示它们并使它们成为有效的模板参数。
std::allocator
被创build为允许开发人员更多地控制如何分配内存。 在许多embedded式系统中,内存受到限制,而且types也不同。 可能不是很多。 此外,内存分配希望被最小化,以避免碎片问题。
分配器还允许从不同的内存池分配。 因此,例如,从小块存储池中分配小尺寸块将会更有效率。
new
和delete
是在dynamic内存中创build一个对象并直接初始化它的直接方法。 分配者更多,因为他们提供了完全控制上述阶段。
使用分配器,我们必须显式地分配堆内存,构造它,销毁它,然后释放内存。
实际上,分配器不应该被用于“正常”的代码, new
和delete
同样可以。 考虑一个像std::map
这样的类,经常以树的forms实现:当一个对象被删除时,是否需要释放整个叶子? 分配器允许你破坏这个对象,但是保留这个内存,这样你就不必再需要它了。
此外,如果你知道更多的控制优化方法,那么你可以专门化一个特定types的分配器,这对于new
和delete
是不可能的。
这个STL成员的原因是为了让开发人员更好地控制内存。 我的意思是说,新运营商本身并不只是一种运营方式。 在最基本的情况下,它执行内存预留,然后用对象填充该空间。
尽pipe我无法想出一个特定的真实世界的案例场景,但是也许应该使用std::allocator
,例如,销毁给定的对象可能会影响内存中的其他对象。
比方说,为了论证,你创build了某种向量,每个元素都与内存中的其他对象双向链接,并且在删除所述向量的时候,要将链接的对象删除引用返回到它。