如何有效地移动具有大量POD成员的班级?例如:
struct{
int a1;
int a2;
int a3;
...
...
...
};
通过'move'我的意思是行为类似于移动语义(std :: move)。
答案 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。