【问题标题】:convert vector<int> to const unique_ptr<const int[]>将 vector<int> 转换为 const unique_ptr<const int[]>
【发布时间】:2020-12-14 06:23:08
【问题描述】:

如何将向量转换/复制到 unique_ptr

这就是我想要实现的(向量来源于另一个上下文,复制到unique_ptr后会被删除。unique_ptr是固定长度的,因此可以更有效地分配)。

std::vector<int> vv {1, 2, 3};

struct
    U {
        U(std::vector<int> v) { // copy constructor
            // copy vector v to unique_ptr u, HOW?
        }

        std::unique_ptr<int[]> u; 
};


U uu {vv}; // copy vector vv to unique_ptr uu, HOW?

我试图创建一个复制构造函数

U(std::vector<int> v) {
    u = std::make_unique<int[]>(v.size()); // OK
    std::copy(v.begin(), v.end(), u); // error: u has no copy constructor
}

那么,我应该如何构造复制构造函数?

事实上,一旦构造完成,我希望 unique_ptr 在长度和内容上都保持不变,所以在我的情况下应该是

std::unique_ptr<int const[]> const u; // const in both length and content

复制构造函数在这两种情况下的外观如何?

案例 1) std::unique_ptr u 案例 2) std::unique_ptr const u

【问题讨论】:

  • 出于性能原因,向量不是最优的我不明白这怎么可能。数组和向量具有相同的性能特征。
  • 出于性能原因,向量不是最优的 std::vectorstd::unique_ptr 之间的性能没有差异。使用矢量,它是工作的工具。
  • 即使存在差异,您也需要很多差异来证明复制整个向量的合理性
  • 您确实应该解释您的性能问题。肯定可以回答你的问题。但是您似乎对为什么使用vectorunique_ptr 相比会出现性能问题存在误解,所以首先应该澄清这一点。
  • unique_ptr 是固定长度的,因此可以更有效地分配向量可以使用reserve,这将同样有效地分配。

标签: c++ vector containers unique-ptr


【解决方案1】:

我试图创建一个复制构造函数

这不是复制构造函数。那是一个转换构造函数。

std::copy(v.begin(), v.end(), u); // error: u has no copy constructor

std::copy 的第三个参数必须是一个迭代器,就像前两个一样。 std::unique_ptr 不是迭代器。

唯一指针指向一个数组。指针是数组的迭代器。所以,你需要的是一个指针。如何从唯一指针中获取指针?使用std::unique_ptr::get成员函数。

您可以通过接受模板化迭代器(或范围)而不是向量来使构造函数更加通用。作为奖励,您可以避免复制两次(也可以通过使用引用来避免)。

unique_ptr 是固定长度的,因此可以更有效地分配

向量和动态数组(例如由唯一指针管理的数组)的分配方式几乎没有区别。即使存在一些差异,复制输入向量进行转换也比不复制它的效率要低得多。

【讨论】:

    【解决方案2】:

    您正在做的事情有几个问题。首先你有两个副本而不是一个(在U 构造函数中),然后你需要在u 上获取实际的迭代器,而不是u 本身。

    为了 const 的正确性,您可以只使用一个允许更改数据的中间唯一指针。

    您的最终代码应如下所示:

    struct U {
        U(const std::vector<int>& v) {
            auto data = std::make_unique<int[]>(v.size());
            std::copy(v.begin(), v.end(), data.get());
            u = std::move(data);
        }
    
        std::unique_ptr<int const[]> u; 
    };
    

    注意:向量与唯一指针一样有效。数据访问模式将是相同的。只有当您 push_back 或擦除时才会产生开销。由于您没有执行任何这些操作,因此只需存储 const vector

    如果您想要一个const std::unique_ptr&lt;int const[]&gt; u,那么您需要添加一个static 方法,该方法会将您的向量转换为std::unique_ptr&lt;int const[]&gt;,并且您的构造函数将在其上使用&amp;&amp; 并将其移动到u 中初始化列表。

    struct U {
        U(std::unique_ptr<int const[]>&& u)
        : u(std::move(u)) {}
    
        static U create(const std::vector<int>& v) {
            auto data = std::make_unique<int[]>(v.size());
            std::copy(v.begin(), v.end(), data.get());
            std::unique_ptr<int const[]> u = std::move(data);
            return U(std::move(u));
        }
    
        const std::unique_ptr<int const[]> u; 
    };
    

    【讨论】:

      猜你喜欢
      • 2016-11-11
      • 1970-01-01
      • 2013-01-19
      • 2015-11-23
      • 2016-08-03
      • 2014-09-20
      • 1970-01-01
      • 2012-05-03
      • 1970-01-01
      相关资源
      最近更新 更多