只有当c++中有活动的东西时,才有一个额外的数据成员
Have an extra data member only when something is active in c++
我有一个队列的实现,类似于带有struct QueueItem { T data;}
的template <typename T> queue<T>
,并且我还有一个单独的库,用于对数据在不同位置的传输进行计时(包括通过该队列从一个生产者线程到消费者线程)。为了做到这一点,我将该定时库中的代码插入到队列的推送和弹出函数中,这样当他们分配BufferItem.data
时,他们也会将我添加的类型为void*
的额外成员分配给该库中的一些定时元数据。也就是说,以前的
void push(T t)
{
QueueItem i;
i.data = t;
//insert i into queue
}
成为
void push(T t)
{
QueueItem i;
i.data = t;
void* fox = timinglib.getMetadata();
i.timingInfo = fox;
//insert i into queue
}
QueueItem来自
struct QueueItem
{
T data;
}
至
struct QueueItem
{
T data;
void* timingInfo;
}
然而,我想实现的是,无论何时时序库未激活,都可以从后一个结构切换到更轻的结构。类似于:
if timingLib.isInactive()
;//use the smaller struct QueueItem
else
;//use the larger struct QueueItem
尽可能便宜。这样做的好方法是什么?
很明显,你不能同时拥有一个大小结构,所以你必须考虑某种形式的继承、指针/引用或并集。
如果T中有"空闲"数据可以被您的timingInfo占用,那么联合将是您的理想选择。如果没有,那么它将和原作一样"沉重"。
使用继承也可能和原来的一样大,因为它会在其中添加一个vtable,这会使它变得过于突出。
因此,下一个选项是只存储一个指针,并将该指针指向要存储的数据,无论是数据还是数据+计时。这种模式被称为"轻量级",即公共数据与被操作的对象分开存储。这可能就是你想要的(取决于时间信息元数据是什么)。
另一种更复杂的选择是有两个保持同步的队列。您将数据存储在一个中,另一个存储相关的计时信息(如果启用)。如果未启用,则忽略第二个队列。这样做的问题是确保2个保持同步,但这是一个组织问题,而不是技术挑战。也许可以创建一个新的Queue类,该类在内部包含两个真正的队列。
我将首先确认我的假设,即这需要是一个运行时选择,并且不能只构建两个启用/禁用定时的不同二进制文件。这种方法在任何方法中都尽可能多地消除了开销。
所以现在让我们假设我们想要不同的运行时行为。需要有运行时决策,因此有几个选项。如果你可以避免多态性的(相对较小的)成本,那么你可以让你的队列多态,并在启动时创建一个合适的实例,然后它的push
会或不会添加额外的数据。
然而,如果这不是一个选项,我相信你可以使用模板来帮助完成你的目的,尽管可能会有一些前期工作,而且它可能会通过额外的代码增加你的二进制文件的大小。
您可以从一个模板开始为类添加计时:
template <typename Timee>
struct Timed : public Timee
{
void* timingInfo;
};
然后一个定时的QueueItem看起来像:
Timed<QueueItem> timed_item;
对于任何不关心时间的东西来说,这个类看起来就像一个QueueItem
:它会根据需要自动向上投射或切片到父级。如果一个方法需要知道定时信息,您可以创建一个重载来知道对Timed<T>
做什么,或者进行运行时检查(针对"是否启用了定时"标志)并向下转换到正确的类型。
接下来,您需要更改Queue
实例化,以了解它是使用基本QueueItem
还是Timed
版本。例如,一个可能机制的非常粗略的草图:
template <typename Element>
void run()
{
Queue<Element> queue;
queue.setup();
queue.process();
}
int main()
{
if(do_timing)
{
run<Timed<QueueItem> >();
}
else
{
run<QueueItem>();
}
return 0;
}
当与Timed
项一起使用时,您"可能"需要对Queue
进行专门化,除非获取元数据是无状态的,在这种情况下,Timed
构造函数可以收集信息并在创建时自行填充。那么Queue
就保持不变,并依赖于您正在使用的实例化。
- 为什么将一个结构的引用设置为等于另一个结构只会更改一个数据成员?
- 在 C++ 中声明 const 对象需要用户定义的默认构造函数.如果我有一个可变成员变量,为什么不呢?
- 大家好,当一个类有一个向量作为它的数据成员时,为什么它的大小总是24?
- 我们可以有一个 setter 成员函数作为从 const 对象引用的 const 吗?
- 在结构向量中搜索一个数据成员,然后打印匹配的所有数据成员
- 从指向成员的指针的模板推导,其中至少有一个指向成员的指针是已知的
- 如何在STD :: MAP中找到具有至少一个数据成员等于密钥的结构的元素
- 是否有必要重载具有另一个类 B 的数据成员的类 A 的赋值运算符和复制构造函数?
- 一个类本身有一个静态成员的功能是什么?
- 参考数据会在const函数中更改另一个数据成员
- 并集:从并集的一个数据成员中读取数据,然后写入另一个
- 我可以初始化一个数据成员,这些成员本身就是头文件中的类
- 对<MyClass> MyClass 的一个数据成员进行排序向量?
- 是否可以有一个"auto"成员变量?
- javascript中的闭包与c++中的类实例(它有一个私有成员和一个公共方法)相当吗
- 在C++中有一个引用成员有什么问题?
- 重构来自/到一个数据成员的读写访问器
- 如何检查一个指针作为一个数据成员在类在c++中已初始化
- 基于另一个数据成员的类数据成员类型
- 为什么“std::string”有一个“find”成员函数