我目前有一个如下课程:
class Element {
Large l1;
OtherLarge l2;
Small s1;
VerySmall s2;
};
其中Large
和OtherLarge
相对较大(约80个字节),而Small
和VerySmall
相当小(约4到16个字节)。
在这些元素上,我以两种方式运作:
s1
和s2
。第二类操作已经相当快,并且可以轻松并行化,因此我想更快地加速第一类操作。与另一个类Element2
比较,我用8字节整数替换了两个大数据成员,什么也没做,告诉我如果我能以某种方式用指针替换直接数据成员l1
和l2
在其他地方动态分配元素的那种或那种,我已经获得了巨大的胜利。
作为参考,所有成员类型都有复制和移动构造函数,可以复制和移动,但移动它们要便宜得多。 Large
和OtherLarge
也会自行分配大量内存,因此分配更多内容并不一定非常糟糕。
是否可能,如果是这样,最好的方法是用一个指向动态分配的对象的指针替换类的直接成员对象;保持直接成员的行为尽可能接近w.r.t构建,破坏,成员变量访问等?如果我天真地使用std::unique_ptr<Large>
,我认为我必须在一半时间取消引用它/专门处理复制?理想情况下,我希望新成员对象的行为就像旧的大成员对象仍然存在一样。
答案 0 :(得分:4)
unique_ptr不会解决您的问题,因为排序可能涉及复制(用于交换)。我相当确定flyweight模式可以解决您的问题。这是一个简单的实现:
class Element_data {
public:
large l1,l2;
};
std::vector<Element_data> data;
class Element {
public:
small s1, s2;
int data_ind;
large &GetLarge1() {
assert(data_ind>=0 && data_ind<data.size);
return data[data_ind].l1;
}
};
std::vector<Element> elements;
...
std::sort(elements.begin(), elements.end(), &mysortfn);
为什么不使用指针?如果向数据向量添加新成员,它们可能会失效。此方法还允许您将数据保存在一起,以便更轻松地加载到缓存中。
补充要点:
编辑:只是为了确保你不会遇到问题,如果不清楚,Element的析构函数不应该破坏数据。您可以为此提供自定义删除。最好的方法是开发一个可以执行此操作的容器,使用擦除功能擦除元素和数据。