向STL容器(例如std::vector)提供带有分配器作为模板参数的区别是什么,例如:
std::vector<int, std::allocator<int>> some_ints;
并提供分配器作为构造函数参数,例如:
std::allocator<int> temp;
std::vector<int> some_ints(temp);
鉴于它们不是同一事物(即,一个提供一个类型,另一个提供一个类型实例)并且可以彼此分开使用,那么两者的优点是什么?
最佳答案
可以彼此分开使用吗?
template参数仅提供类型。您仍然需要一个实例。这是不可分离的。
这就像有一个功能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
参数的 vector 调用时,便会创建新的Allocator
对象(在默认情况下,它很可能什么都不做,但程序的逻辑流程如前所述)。您不能传递不适合
Allocator
的内容,因为这样会导致类型不匹配,或者在这种情况下恰好是替换失败。您可以在不触及
vector
定义的情况下做一个非常非标准的工作,就是定义DerivedAllocator
,它是从Allocator
实例化并作为参数传递的。因此,例如:vector<T> v( DerivedAllocator<T>() );
但是我无法在我的头上拿出一个用于这种结构的用例。有一个很好的用例,请参见下面的附录。
Allocator
模板参数有什么用?在某些系统中,您拥有不止一种类型的内存,因此提供单独的分配器(通常是单独的分配器类型)可能会很有用。例如:
SRamAllocator
,RamAllocator
等。这在嵌入式系统中很常见。我知道在某个地方有一个实现中的内存模型实际上并没有释放,当您释放它时,这是一个丢失的块。本质上,它是一个移动的指针。理由是它非常快,因为它没有任何逻辑可以跟踪由
free
ing引起的“漏洞”块。您不希望在new
/delete
模式繁重的情况下使用它。allocator
构造函数参数有什么用?在有状态分配器的情况下,这是有意义的。假设您要拥有两个相同类型的存储。例如。跟踪某些内存使用情况,或由于某种原因而拥有多个逻辑“内存库”的情况。您可能想为程序中的每个线程创建一个分配器,因此更容易维护正确的CPU/内存亲缘关系。
创建新对象时,需要告诉哪个分配器实例应该处理它。
从技术上讲,您可以为每个实例使用不同的类型来实现所有内容,但这会降低可能的运行时动态性的可用性。
注意:不允许默认分配器和c++ 11之前的自定义分配器具有状态,因此它们基本上是以完全静态的方式实现的。实际上,与您使用的分配器实例无关紧要。这就是为什么默认
Allocator()
有效的原因。因此,从理论上讲,无需实例化它们,并且可以只使用类型和静态接口(interface)来工作……如果标准如此规定的话。但是,故意不采用这种方式来允许具有内部状态的分配器类型(此语句是个人观点)。
重要说明:我错过了c'tor参数分配器的一项重要功能,很可能是存在的理由。 多态分配器。 在这里详细描述:polymorphic_allocator: when and why should I use it?
基本上,使用不同的
Allocator
类型将更改对象的整个类型,因此,结束于基本上相同的对象,只是分配器的不同。在某些情况下,这是非常不希望的。为了避免这种情况,可以编写一个多态分配器,并在类型中使用基本分配器,并将具体实现用作运行时参数。 因此,可以使用不同的存储引擎来拥有完全相同类型的对象。 因此,使用参数会带来一些开销,但会减少分配器的状态,而不会将其分配给该类型,更多的是实现细节。
关于c++ - 在C++容器中作为模板参数提供的分配器与作为构造函数参数提供的分配器之间的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37801151/