将大型成员对象移出课堂?

时间:2015-10-03 19:32:05

标签: c++ class c++11 memory

背景/示例:

我目前有一个如下课程:

class Element {
  Large l1;
  OtherLarge l2;
  Small s1;
  VerySmall s2;
};

其中LargeOtherLarge相对较大(约80个字节),而SmallVerySmall相当小(约4到16个字节)。

在这些元素上,我以两种方式运作:

  • 以各种方式对它们进行排序。在此期间,只能访问/需要成员s1s2
  • 以各种方式组合大成员(例如矩阵 - 矩阵乘法)。

第二类操作已经相当快,并且可以轻松并行化,因此我想更快地加速第一类操作。与另一个类Element2比较,我用8字节整数替换了两个大数据成员,什么也没做,告诉我如果我能以某种方式用指针替换直接数据成员l1l2在其他地方动态分配元素的那种或那种,我已经获得了巨大的胜利。

作为参考,所有成员类型都有复制和移动构造函数,可以复制和移动,但移动它们要便宜得多。 LargeOtherLarge也会自行分配大量内存,因此分配更多内容并不一定非常糟糕。

具体问题

是否可能,如果是这样,最好的方法是用一个指向动态分配的对象的指针替换类的直接成员对象;保持直接成员的行为尽可能接近w.r.t构建,破坏,成员变量访问等?如果我天真地使用std::unique_ptr<Large>,我认为我必须在一半时间取消引用它/专门处理复制?理想情况下,我希望新成员对象的行为就像旧的大成员对象仍然存在一样。

1 个答案:

答案 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指向相同的数据

编辑:只是为了确保你不会遇到问题,如果不清楚,Element的析构函数不应该破坏数据。您可以为此提供自定义删除。最好的方法是开发一个可以执行此操作的容器,使用擦除功能擦除元素和数据。