为什么不像std :: vector这样的标准容器实现接口? [英] Why don't standard containers like std::vector implement interfaces?

查看:49
本文介绍了为什么不像std :: vector这样的标准容器实现接口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想存储一个队列向量.

I want to store a vector of queues.

队列可能具有不同的模板类型,因此我无法将它们存储在相同的向量中.

The queues may have different template types therefore I cannot store them in the same vector.

std::queue<int> aQueue1
std::queue<std::string> aQueue2
std::queue<float> aQueue3
std::vector<std::queue> aVec // Doesn't work because std::queue needs template arguments

我可以在向量中存储指向队列的指针,但是队列并不都实现相同的基类(例如IQueue).

I can store pointers to the queues in the vector however the queues do not all implement the same base class (Eg IQueue).

std::vector<std::IQueue*> aVec //IQueue does not exist

为什么不存在?我有什么选择?

Why does this not exist? What are my options?

在我的情况下,用法是我要检查所有队列是否为空. myqueue.empty()

In my case, the usage is that I want to check if all the queues are empty. myqueue.empty()

推荐答案

您在此处使用的 std 库的一部分- std :: queue -来自称为标准模板库"的库.

The part of the std library that you are using here -- std::queue -- descends from a library called "the standard template library".

在其中,Alexander Stepanov得出结论,您可以将容器操作与操作的数据脱钩,并将算法与其操作的容器脱钩.所有这些都在生成接近于手工C的性能的代码.

In it, Alexander Stepanov worked out you could decouple container operations from the operated on data, and algorithms from the containers they operate on. All while generating code that was close to the performance of hand-crafted C.

这太神奇了.

您可以使用代码生成实用程序执行类似的操作,但是编译器或调试器无法理解这样生成的代码,至少是如何将其连接回原始代码.STL使每个C ++用户都可以使用性能经过调整且无错误的实现的红黑树,而无需考虑太多.

You could do something similar with code generation utilities, but such generated code was not understandable by the compiler or debugger, at least how it connected back to the original. The STL let every C++ user use a red-black tree with tweaked performance and bug-free implementations without even thinking much about it.

现在,C ++的原则之一就是您不用为不使用的东西付费.将虚拟接口添加到对象时,会增加一堆开销.

Now, one of the principles of C++ is that you don't pay for what you don't use. When you add a virtual interface to an object, there is a bunch of overhead that is added.

首先,每个实现类的虚拟功能表必须在运行时存在.其次,添加RTTI.第三,内联机会消失了.第四,实现对象必须带有一个额外的vtable指针.第五,分派到方法需要额外的间接层.第六,像迭代器这样的连锁类型变得越来越复杂.

First, a per-implementation-class virtual function table has to exist at runtime. Second, RTTI is added. Third, inlining opportunities evaporate. Forth, the implementation objects have to carry around an extra vtable pointer. Fifth, dispatch to methods requires extra layers of indirection. Sixth, knock-on types like iterators get increasingly complex.

所有这些费用都不由 std :: queue< int> 承担.如果您是基于块分配的双数组表编写自己的自定义C队列,则 std :: queue< int> 的实现大致就是您将得到的.

All of these costs are not carried by std::queue<int>. The implementation of std::queue<int> is roughly what you'd get if you wrote your own custom C queue based off block-allocated double-array tables.

我的意思是,如果您想要一个队列,您可能不会写.但是,如果您有很多时间,您可能会做到.

I mean, you probably wouldn't write that if you wanted a queue. But if you had lots of time you might.

其他语言选择了不同的路径.诸如Java和C#之类的语言几乎所有对象都通过继承和虚拟表进行堆分配.对象实际上是对对象的垃圾回收引用,并且内存位置几乎是不可能的.

Other languages have chosen a different path. Languages like Java and C# have almost all objects heap-allocated with inheritance and virtual tables. Objects are actually garbage collected references to objects, and memory locality is near impossible.

在大多数任务中,这样做的成本大约将性能降低了2到3倍.他们可以在狭窄的情况下使用外部库来解决此问题,或者通过非常仔细地编写代码来使其优化程序可以消除所有对象开销的方法.

The cost of this is roughly a 2x to 3x performance reduction in most tasks. They can get around this in narrow cases by either using external libraries, or by very carefully writing code that their optimizer can remove all of the object overhead from.

对于许多人来说,性能降低2到3倍是可以的.毕竟,对性能的投资是可以互换的,并且在Java和C#中,许多任务要容易得多.因此,您可以编写一个更快的应用程序,使之陷入C#/Java中,然后将工作重点放在关键路径上.将汗水投入到代码中时,将代码的性能提高一倍是非常典型的.

For many people that 2x to 3x reduction in performance is a-ok. After all, investment in performance is fungible, and many tasks are much easier in Java and C#. So you can write a quicker app that hobbles along in C#/Java, then focus your work on the critical path. Doubling the performance of code is pretty typical when you put brain-sweat into it.

C ++并不是真正的OO语言.它具有编写C ++的功能,面向对象和过程方式.

C++ isn't really an OO language. It has functional, OO and procedural ways of writing C++.

关于如何解决?您编写自己的 own 队列抽象.我脑海中浮现出四种抽象队列的方法.

As to how you get around it? You write your own queue abstraction. Off the top of my head I can think of four ways to abstract a queue.

  1. 您可以编写自己的基本队列类.具有自己的基本队列值.

  1. You can write your own base queue class. With its own base queue values.

您可以编写一个 std :: variant 的队列,或者一个 std :: variant 队列.

You can write a queue of std::variants, or a std::variant of queues.

您可以编写 std :: any 的队列.

您可以键入擦除队列操作并构建自己的vtable实现以允许多态值类型.

You can type-erase the queue operations and build your own vtable implementation to allow polymorphic value types.

哪个是最好的?这将取决于您的代码编写能力,问题空间的详细信息以及所使用的C ++版本.

Which one is best? It will depend on your ability to write code, the details of your problem space, and the version of C++ you are working with.

这篇关于为什么不像std :: vector这样的标准容器实现接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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