在C ++容器中作为模板参数提供的分配器与作为构造函数参数提供的分配器之间的区别? [英] Difference between allocator supplied as template parameter and allocator supplied as constructor argument in C++ containers?

查看:133
本文介绍了在C ++容器中作为模板参数提供的分配器与作为构造函数参数提供的分配器之间的区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为STL容器(例如std :: vector)提供分配器作为模板参数有什么区别,例如:

  std :: vector< int,std :: allocator< int>> some_ints; 

并提供分配器作为构造函数参数,例如:

  std :: allocator< int>温度
std :: vector< int> some_ints(temp);

两者的优点是什么,因为它们不是同一件事情(例如,一个耗材

解决方案

可以彼此分开使用吗?



template参数仅提供类型。您仍然需要一个实例。



这就像具有函数 template< typename Type> f(Type instance); 并询问 Type instance 有什么区别,它们可以分别使用吗?两者的优点是什么?如果您确实了解什么是模板,类型和实例/对象,这没有多大意义。



(为简单起见,它是c ++ 11)



这里您有 vector 的类型模板:

  template< 
类为T,
类为Allocator = std :: allocator< T>
>类向量

这是默认的构造函数:

 显式向量(const Allocator& alloc = Allocator()); 

总是提供 Allocator 的实例作为 alloc 参数。在这方面,所有其他调用都类似。默认情况下,默认构造新的 Allocator 对象。因此,从语义上讲,每当不使用指定 allocator 参数的矢量调用时,就确实会创建新的 Allocator 对象(在默认情况下,最有可能什么都不做,但是程序的逻辑流程如前所述)。



您不能传递不适合 Allocator的内容,因为您会遇到类型不匹配,或者在这种情况下恰好是替换失败。



一个非常非标准的方法,您无需碰触 vector 的定义是定义 DerivedAllocator ,它源自 Allocator 实例化它并作为参数传递。因此,例如:

  vector< T> v(DerivedAllocator T(())); 

但是我无法提出用于这种构造的用例有一个很好的用例,请参见下面的附录。



什么是 Allocator 模板参数有用吗?



在某些系统中,您拥有不止一种类型的内存,因此提供单独的分配器(通常是单独的分配器类型)可能很有用。 )。例如: SRamAllocator RamAllocator ,等等。



此在嵌入式系统中很常见。我知道在某个地方有一个实现中的内存模型实际上并没有释放,当您释放它时,这是一个丢失的块。本质上,它是一个移动的指针。理由是它之所以非常快,是因为它没有任何逻辑来跟踪免费 ing造成的漏洞。您不希望使用带有大量 new / 删除模式的方案。



分配器构造函数有什么用?



在有状态分配器。假设您要拥有两个相同类型的存储。例如。跟踪某些内存使用情况,或由于某种原因而拥有多个逻辑内存库的情况。您可能希望为程序中的每个线程创建一个分配器,因此更容易维护正确的CPU /内存关联。



创建新对象时,需要告诉哪个分配器 instances 应该照顾它。



您可以在技术上实现所有实例,而只是对每个实例使用不同的类型,但这将



注意:默认分配器和c ++ 11之前的自定义分配器不允许具有状态,因此基本上以完全静态的方式实现。实际上,与您使用的分配器实例无关紧要。这就是为什么默认 Allocator()起作用的原因。



因此,从理论上讲,无需实例化它们,并可以只使用类型和静态接口...如果标准是这样的话。但这不是故意让这种分配器类型具有内部状态(这是个人观点)



重要事项:我错过了c'tor参数分配器的一项重要功能,很可能是 raison d'être多态分配器。在此处详细描述: polymorphic_allocator:我何时以及为什么要使用它?



基本上,使用不同的 Allocator 类型会改变对象的整体类型,因此,结束于基本上相同的对象,只是分配器不同。在某些情况下,这是非常不希望的。为了避免这种情况,可以编写一个多态分配器,并在类型中使用基本分配器,并将具体实现用作运行时参数。 因此,可以使用不同的存储引擎来拥有完全相同类型的对象。因此,使用参数会产生一些开销,但会减少分配器的状态,使其不再被烙印到该类型上,而是更多地用于实现。详细信息。


What's the difference between supplying an STL container (for example, std::vector) with an allocator as a template parameter, eg.:

std::vector<int, std::allocator<int>> some_ints;

and supplying an allocator as a constructor argument, eg:

std::allocator<int> temp;
std::vector<int> some_ints(temp);

and what are the advantages of either, given that they are not the same thing (ie. one supplies a type, the other a type instance) and can be used separately from each other?

解决方案

Can be used separately from each other?

The template parameter just supplies the type. You still need an instance. It's not separable.

It's like having a function template<typename Type> f(Type instance); and asking what is the difference between Type and instance, can they be used separately and what are the advantages of either. It does not make much sense if you do understand what is a template, type and an instance/object.

(for the sake of simplicity it's c++11)

Here you have type template for vector:

template<
    class T,
    class Allocator = std::allocator<T>
> class vector;

And here is the default constructor:

explicit vector( const Allocator& alloc = Allocator() );

There always is an instance of Allocator provided as alloc parameter. All other invocation are similar in this regard. By default it is default constructed new Allocator object. So, semantically, whenever you do not use invocation of vector specifying allocator parameter, you do create new Allocator object (which in default case most probably does nothing, but the logical flow of the program is as described).

You cannot pass something that would not fit Allocator because you would get type-mismatch, or precisely in this case a substitution failure.

One pretty non-standard you could do without touching the definition of vector is to define DerivedAllocator which derives from Allocator instantiate it and pass as an argument. So for example:

vector<T> v( DerivedAllocator<T>() );

But I am not able to come up with a use-case for such construction on the top of my head. There is a good use-case, see the addendum below.

What is the Allocator template parameter useful for?

In some system you have more than one type of memory, so it might be useful to provide separate allocators (presicely separate allocator types). E.g: SRamAllocator, RamAllocator, etc.

This is quite common in embedded systems. I know that somewhere there there is a memory model in implementation which actually does not free, when you free it it's a lost chunk. It's essentially a moving pointer. The rationale is that it's extremely fast because it does not have any logic to trace blocks of "holes" caused by freeing. You wouldn't want to use it scenarios with heavy new/delete patterns.

What is the allocator constructor parameter useful for?

It makes sense in case of stateful allocators. Imagine you want to have two storages of the same type. E.g. to track some memory usage, or whatever reason you come with to have more than one logical "memory banks". You may want to create an allocator for each thread in your program, so it's easier to maintain correct CPU/memory affinity.

When you create a new object, you need to tell which of the allocators instances should take care of it.

You could technically implement everything just using different type for each instance, but that would strip down the usability of possible run-time dynamism.

NOTE: Default allocator and pre-c++11 custom allocators are disallowed to have a state, so they basically that to be implemented in a fully static way. It actually does not matter instance of Allocator you use. That is why the default Allocator() works.

So, theoretically one would no need then to instantiate them, and could work with just type and a static interface... if the standard said so. But it was deliberately not made this way to allow allocator types with an internal state (this sentence is a personal opinion).

IMPORTANT ADDENDUM: I've missed one important perk of c'tor parameter allocator, which is quite possibly it's raison d'être. Polymorphic allocators. Is described in detail here: polymorphic_allocator: when and why should I use it?

Basically, using different Allocator type would change the whole type of the object, so one end's up with basically the same object which differ only by allocator. This is under certain circumstances highly undesirable. To avoid it, one can write a polymorphic allocators and use base allocator in the type, and concrete implementations as the runtime parameters. Therefore, one can have object of exactly the same type using different storage engines. So using parameter has some overhead, but it reduces status of the allocator from being iron branded onto the type, to more of an implementational detail.

这篇关于在C ++容器中作为模板参数提供的分配器与作为构造函数参数提供的分配器之间的区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆