使用POD高效移动课程

时间:2012-07-21 02:35:10

标签: c++ c++11

如何有效地移动具有大量POD成员的班级?例如:

struct{
    int a1;
    int a2;
    int a3;
    ...
    ...
    ...
};

通过'move'我的意思是行为类似于移动语义(std :: move)。

4 个答案:

答案 0 :(得分:12)

POD不动,他们只是复制。因为没有间接性。因此,只需使用普通的赋值,并要求编译器针对您的任何效率进行优化。记得在系统地测量之前(地球上你做的不同)和之后。还要考虑浪费的程序员时间,即金钱,是否值得微观优化。

答案 1 :(得分:12)

这个问题表明对C ++ 11中的动作缺乏了解。

复制具有指针或拥有资源的对象时,有两种方法可以使该复制发生。您可以复制指针/资源引用,也可以分配新的对象/资源,并将原始对象/资源的值复制到新的对象/资源中。

在第一种情况下,您将留下两个引用相同对象的对象。 Qt做了很多。如果您使用一个对象来修改它引用的内容,那么您也在修改另一个对象。您通常需要某种引用计数器,以便不会双重删除指针或双重释放资源。

在第二种情况下,您将留下两个完全独立的对象。这通常称为“值语义”,因为如果将一个POD复制到另一个POD,则之后会有两个完全独立的对象。改变一个不会改变另一个。

移动语义是一种C ++ 11机制,允许通常具有值语义的对象在特定条件下具有引用语义。它本质上允许对象窃取另一个对象实例引用的指针/资源。

例如,取std::vector;这只是一个动态分配和调整大小的数组的包装器。与大多数C ++标准库对象一样,vector实现了值语义。如果复制vector,新向量必须分配一个新数组,并将旧元素中的每个元素复制到新数组中。完成后,您将拥有两个完全独立的阵列。

移动语义是一种将vector中包含的数组转移到另一个中的方法。在操作之后,移动源对象是“空的”(技术上处于未定义状态,但它实际上与它分配的数据分开)。新vector现在具有与旧vector完全相同的指针;新的vector将删除它未分配的内存。

如您所见,这完全基于拥有资源的对象的概念。 vector分配并拥有一个数组;它的析构函数会破坏它。这就是你如何定义所有权。运动是关于转让所有权

POD不能表达指针或资源的所有权,因为POD必须具有琐碎的析构函数(即:不执行任何操作的析构函数)。由于POD无法表达所有权,因此无需移动。如果对象没有任何内容,则无法在对象之间转移所有权。

答案 2 :(得分:8)

你必须带来工程判断才能发挥作用。想象一下,您正在讨论是否使用std::array<int, N>std::vector<int>N项目的示例,其中N是编译时常量。

N非常小时,std::array<int, N>是明显的赢家,因为没有堆分配。副本(以及相当于副本的动作)很便宜。

N非常大时,std::vector<int>是明显的赢家,因为虽然有一个堆分配,并且可以移动vector,但只需移动3个字,无论N的大小。

N == 3时,毫无疑问哪个是更好的选择。当N == 3,000,000毫无疑问哪个是更好的选择。

作为设计师,你的工作是进入这两个极端之间的灰色区域并做出正确的决定。没有永远正确的决定。针对预期用例的性能测量有很长的路要走。使用<chrono>进行性能测量。如果您不知道<chrono>是什么,请搜索stackoverflow。

答案 3 :(得分:1)

创建一个类以指向具有POD的类,并在前者上使用std :: move。

相关问题