【发布时间】:2017-12-02 10:37:19
【问题描述】:
考虑以下示例:
- 我有一个抽象类
socket,它为一个不错的面向对象套接字定义了一些虚拟接口(例如,send和receive)。 - 然后该类以多种方式专门化,(例如,在我的情况下,我可以有一个
TCP套接字或UDT套接字,它们以不同的方式工作(UDT基于底层@987654327以@socket 为例),但它们具有相同的接口,即可以例如send和receive。 - 我有一个
connection类,它应该以某种方式包装一个套接字,添加很多功能(例如,发送和接收对象的模板方法,它序列化它们,一切都很漂亮)。
现在,我可以在connection 中做的最简单的事情就是拥有一个socket * 指针。 connection 然后可以在其构造函数中接受一个指针,一切都很好。但是,那里存在一个性能问题:每当我的 connection 对象想要与我的 socket 对象通信时,都会出现需要时间的取消引用。
我想做的是让socket 成为connection 的成员。不要误会我的意思:我知道,如果没有别的,socket 的不同专业可以有不同的大小,所以我不能简单地做这样的事情:socket my_pretty_socket;
我的想法
我想知道的是,如果下面的想法没有任何意义,以及为什么。
我有一组有限的socket 可能的专业化。如果我建立一些template any <typename base, typename... specializations> 会怎样:
- 分配与最大专业化一样多的
chars 数组。 - 提供模板构造函数,将其参数转发到指定特化的构造函数,并使用分配数组上的放置
new来创建对象。 - 行为类似于对
socket的引用,例如通过提供operator * ()或将每个调用转发到socket的接口到它正在存储的专业化。
通过这种方式,我将对象作为connection 的成员就位,并且我将保留接口的所有良好属性,同时节省内存事务。
- 这个想法很愚蠢吗?为什么?
- 是否已有解决方案可以做到这一点?我确信我不会是唯一遇到此类问题的人。
【问题讨论】:
-
“是否已经有解决方案可以做到这一点?”
boost::asio -
呃,但在您的解决方案中,您仍然必须取消引用。您仍然通过指向套接字的指针进行调用,因此您仍然通过 vtable。您唯一要更改的是数据的存储位置。这是你的意图吗?
-
我的意思是,实际上最简单、最高效的做法就是完全摆脱继承,只需将
connection模板化为socket的确切类型。然后您支付零间接成本,这比您尝试做的要简单得多。但是connection现在的类型取决于它激活的套接字,因此您无法在运行时决定使用哪个连接(除非您在更高级别擦除类型)。这是个问题吗? -
@NirFriedman 与网络 I/O 的成本相比?我认为不会。
-
我在这里与@Barmar 在一起:缓存未命中,取消引用,与什么相比“慢”?这里我们讨论的是网络 I/O:与缓存未命中或“缓慢”取消引用相比,通过线路发送一个字节需要更多的时间。寻找干净且可维护的代码,阅读有关单一职责原则和关注点分离的信息。并且只有在衡量之后才开始担心性能。在大多数(不是全部)真实场景中,您对取消引用性能的担忧可以忽略不计。
标签: c++ memory abstract-class virtual