背景/例子:
我目前有一个类如下:
class Element {
Large l1;
OtherLarge l2;
Small s1;
VerySmall s2;
};
哪里Large
和 OtherLarge
相对较大(~80 字节),而 Small
和 VerySmall
相当小(~4 到 16 字节)。
在这些元素上,我有两种操作方式:
- 以各种方式对它们进行分类。在此期间,只有成员(member)
s1
和s2
被访问/需要。 - 以各种方式组合大型成员(例如矩阵-矩阵乘法)。
第二类操作已经相当快并且可以轻松并行化,因此我想进一步加快第一类操作的速度。与另一类比较Element2
我用 8 字节整数替换了两个大数据成员什么都不做告诉我,如果我能以某种方式替换直接数据成员 l1
和 l2
通过某种指向其他地方动态分配元素的指针,我已经大获全胜。
作为引用,所有成员类型都有复制和移动构造函数,并且可以复制和移动,但移动它们要便宜得多。 Large
和 OtherLarge
自己也分配了很多内存,所以分配多一点并不一定很糟糕。
具体问题
是否有可能,如果可以,最好的方法是用指向别处动态分配对象的指针替换类的直接成员对象;尽可能地保留直接成员的行为 w.r.t 构造、破坏、成员变量访问等?如果我使用 std::unique_ptr<Large>
天真地,我假设我必须有一半时间取消引用它/特别注意复制?理想情况下,我希望新成员对象的行为就像旧的大成员对象仍然存在一样。
最佳答案
unique_ptr 不会解决您的问题,因为排序可能涉及复制(用于交换)。我相当确定享元模式可以解决您的问题。这是一个简单的实现:
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);
为什么不用指针?如果您向数据 vector 添加新成员,它们可能会失效。此外,这种方法还允许您将数据保存在一起,这样它就可以更容易地加载到缓存中。
补充点:
- 如果您要永久删除一个元素,您也应该删除数据。
- 添加新成员非常简单
- 在排序或者其他一些操作的时候,多个Element指向同一个数据是安全的
编辑:为了确保您在不清楚的情况下不会遇到问题,Element 的析构函数不应破坏数据。您可以为此提供自定义删除器。最好的方法是开发一个可以执行此操作的容器,使用删除功能删除元素和数据。
关于c++ - 将大型成员对象移出类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32926655/