gpt4 book ai didi

c++ - 为什么像 std::vector 这样的标准容器不实现接口(interface)?

转载 作者:行者123 更新时间:2023-12-01 14:09:33 25 4
gpt4 key购买 nike

我想存储一个队列 vector 。

队列可能有不同的模板类型,因此我不能将它们存储在同一个 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

我可以在 vector 中存储指向队列的指针,但是队列并不都实现相同的基类(例如 IQueue)。
std::vector<std::IQueue*> aVec //IQueue does not exist

为什么这不存在?
我有哪些选择?

就我而言,用法是我想检查所有队列是否为空。 myqueue.empty()

最佳答案

std的部分您在此处使用的库 -- std::queue -- 源自一个名为“标准模板库”的库。

在其中,Alexander Stepanov 发现您可以将容器操作与被操作的数据解耦,将算法与它们操作的容器解耦。同时生成接近手工 C 语言性能的代码。

这太棒了。

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

现在,C++ 的原则之一是你不用为你不使用的东西付费。当您向对象添加虚拟接口(interface)时,会增加大量开销。

首先,每个实现类的虚函数表必须在运行时存在。其次,增加了RTTI。第三,内联机会消失。第四,实现对象必须携带一个额外的 vtable 指针。第五,分派(dispatch)到方法需要额外的间接层。第六,像迭代器这样的链式类型变得越来越复杂。
std::queue<int> 不承担所有这些费用。 . std::queue<int>的执行如果您基于 block 分配的双数组表编写自己的自定义 C 队列,大致就是您会得到的。

我的意思是,如果你想要一个队列,你可能不会写那个。但如果你有很多时间,你可能会。

其他语言选择了不同的路径。像 Java 和 C# 这样的语言几乎所有的对象都通过继承和虚拟表进行堆分配。对象实际上是对对象的垃圾收集引用,并且内存局部性几乎是不可能的。

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

对于许多人来说,性能降低 2 到 3 倍是可以的。毕竟,对性能的投资是可替代的,许多任务在 Java 和 C# 中要容易得多。因此,您可以编写一个在 C#/Java 中蹒跚前行的更快应用程序,然后将您的工作重点放在关键路径上。当您投入大量精力时,代码性能翻倍是非常典型的。

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

至于你如何绕过它?您编写自己的队列抽象。在我的脑海中,我可以想到四种抽象队列的方法。

  • 您可以编写自己的基本队列类。具有自己的基本队列值。
  • 你可以写一个std::variant的队列s,或 std::variant的队列。
  • 你可以写一个std::any的队列.
  • 您可以对队列操作进行类型删除并构建自己的 vtable 实现以允许多态值类型。

  • 哪个最好?这取决于您编写代码的能力、问题空间的详细信息以及您正在使用的 C++ 版本。

    关于c++ - 为什么像 std::vector 这样的标准容器不实现接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61330098/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com