可以分开使用吗?
模板参数只提供类型。你仍然需要一个实例。不可分离。
就像有一个函数template<typename Type> f(Type instance);,问Type和instance有什么区别,能不能单独使用,各自有什么优势。如果您确实了解什么是模板、类型和实例/对象,这没有多大意义。
(为简单起见是 c++11)
这里有vector 的类型模板:
template<
class T,
class Allocator = std::allocator<T>
> class vector;
这是默认构造函数:
explicit vector( const Allocator& alloc = Allocator() );
总是有一个Allocator 的实例作为alloc 参数提供。在这方面,所有其他调用都是相似的。默认情况下,它是默认构造的新 Allocator 对象。因此,从语义上讲,每当您不使用指定allocator 参数的向量时,您确实会创建新的Allocator 对象(在默认情况下很可能什么都不做,但程序的逻辑流程如所述)。
你不能传递不适合 Allocator 的东西,因为你会得到类型不匹配,或者在这种情况下恰好是替换失败。
在不触及vector 的定义的情况下,您可以做的一个非常非标准的做法是定义派生自Allocator 的DerivedAllocator 实例化它并作为参数传递。比如:
vector<T> v( DerivedAllocator<T>() );
但我无法想出一个用于这种构造的用例。有一个很好的用例,请参阅下面的附录。
Allocator 模板参数有什么用处?
在某些系统中,您拥有不止一种类型的内存,因此提供单独的分配器(确切地说是单独的分配器类型)可能很有用。例如:SRamAllocator、RamAllocator等
这在嵌入式系统中很常见。我知道在某个地方有一个内存模型在实现中实际上并没有释放,当你释放它时它是一个丢失的块。它本质上是一个移动指针。理由是它非常快,因为它没有任何逻辑来跟踪由freeing 引起的“漏洞”块。您不会希望在具有大量 new/delete 模式的场景中使用它。
allocator 构造函数参数有什么用处?
在有状态分配器的情况下是有意义的。想象一下,您想拥有两个相同类型的存储。例如。跟踪一些内存使用情况,或者您拥有多个逻辑“内存库”的任何原因。您可能希望为程序中的每个线程创建一个分配器,这样更容易维护正确的 CPU/内存关联。
当你创建一个新对象时,你需要告诉实例应该由哪个分配器来处理它。
从技术上讲,您可以只为每个实例使用不同的类型来实现所有内容,但这会降低可能的运行时动态的可用性。
注意:默认分配器和 c++11 之前的自定义分配器不允许有状态,因此它们基本上是以完全静态的方式实现的。实际上,您使用的分配器实例并不重要。这就是默认 Allocator() 有效的原因。
所以,理论上人们不需要实例化它们,并且可以只使用类型和静态接口......如果标准这么说的话。但是故意不这样做是为了允许分配器类型具有内部状态(这句话是个人意见)。
重要附录:我错过了 c'tor 参数分配器的一项重要功能,这很可能是 存在的理由。 多态分配器。这里有详细描述:polymorphic_allocator: when and why should I use it?
基本上,使用不同的Allocator 类型会改变对象的整个类型,因此最终会得到基本相同的对象,只是分配器不同。这在某些情况下是非常不希望的。为了避免这种情况,可以编写多态分配器并在类型中使用基分配器,并将具体实现作为运行时参数。 因此,可以使用不同的存储引擎拥有完全相同类型的对象。因此使用参数有一些开销,但它减少了分配器的状态,从被烙印到类型上,更多的是一种实现详细。