【问题标题】:Efficiently moving a class with PODs使用 POD 高效移动班级
【发布时间】:2012-07-20 07:14:11
【问题描述】:

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

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

“移动”是指行为类似于移动语义 (std::move)。

【问题讨论】:

  • 我不认为它比简单的分配更快。
  • 如果您可以将所有这些存储在一个数组中,请动态分配它并窃取指针。否则,分配可能是你最好的选择。

标签: c++ c++11


【解决方案1】:

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

【讨论】:

  • 当您说“要求编译器优化效率”时,除了使用 inline 之外,您还有什么意思?
  • @johnbakers 我相信,作者的意思是“-O3”之类的。
【解决方案2】:

这个问题暴露出对 C++11 中运动的用途缺乏了解。

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

在第一种情况下,您会得到两个对象,它们都引用了 same 对象。 Qt 经常这样做。如果您使用一个对象来修改它所引用的内容,那么您也在修改另一个对象。您通常需要某种引用计数器,以免双重删除指针或双重释放资源。

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

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

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

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

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

POD 不能表示指针或资源的所有权,因为 POD 必须具有普通的析构函数(即:不做任何事情的析构函数)。因为 POD 不能表达所有权,所以 没有东西可以移动。如果对象不拥有任何东西,则不能在对象之间转移所有权。

【讨论】:

    【解决方案3】:

    您必须发挥工程判断力。想象一个例子,您正在讨论是使用 std::array<int, N> 还是 std::vector<int>N 项目,其中 N 是编译时常量。

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

    N 非常大时,std::vector<int> 是明显的赢家,因为虽然存在堆分配,但无论@ 大小如何,只要移动 3 个字,就可以在 vector 周围移动987654330@.

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

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-08-09
        • 1970-01-01
        • 1970-01-01
        • 2022-06-16
        • 2023-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多