【问题标题】:To copy a vector of unique pointer into new vector将唯一指针向量复制到新向量中
【发布时间】:2014-09-12 02:39:31
【问题描述】:

当我编译下面的代码时,我得到一个编译错误:

std::vector<std::unique_ptr<boxIndex>> tmpVec;
for(const auto& it: hrzBoxTmpMap){
    for(const auto& it2: hrzBoxVec){
        std::copy_if(hrzBoxVec.begin(), hrzBoxVec.end(), tmpVec.begin(), [&](std::unique_ptr<boxIndex>& p)
        {
            return !(it.second == p->getTop() &&
                     it.first != p->getLeft() );
        });
    }
}

编译错误是:

/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_algo.h: 

> In instantiation of ‘_OIter std::copy_if(_IIter, _IIter, _OIter,
> _Predicate) [with _IIter = __gnu_cxx::__normal_iterator<std::unique_ptr<boxIndex>*, std::vector<std::unique_ptr<boxIndex> > >; _OIter =
> __gnu_cxx::__normal_iterator<std::unique_ptr<boxIndex>*, std::vector<std::unique_ptr<boxIndex> > >; _Predicate =
> smoothHrzIndexing(std::vector<std::unique_ptr<boxIndex>
> >&)::<lambda(std::unique_ptr<boxIndex>&)>]’: test_word_2.cpp:282:5:   required from here
> /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_algo.h:990:6:
> error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>&
> std::unique_ptr<_Tp, _Dp>::operator=(const std::unique_ptr<_Tp, _Dp>&)
> [with _Tp = boxIndex; _Dp = std::default_delete<boxIndex>]’ In file
> included from
> /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/memory:86:0,
>                  from test_word_2.cpp:8: /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/unique_ptr.h:263:19:
> error: declared here

有人可以帮我解决这个问题吗?

【问题讨论】:

  • 您无法复制需要移动它们的 unique_ptr。
  • 您希望新向量对原始对象的副本具有 unique_ptrs 吗?
  • 有趣的问题。我不知道如何使用标准算法来做到这一点。有copy_if 但没有move_if。您可以交换向量并在新向量上使用 remove_if。
  • 按照@NeilKirk 的建议,只需交换和 remove_if。
  • 你不需要复制向量,交换速度很快。

标签: c++ c++11 vector constants


【解决方案1】:

你可以做的是使用std::move_iterator&lt;...&gt;,例如使用下面的东西(这是一个SSCCE展示了关键点:

#include <iostream>
#include <iterator>
#include <vector>
#include <memory>

int main()
{
    std::vector<std::unique_ptr<int>> boxVec;
    boxVec.emplace_back(new int(1));
    boxVec.emplace_back(new int(17));
    boxVec.emplace_back(new int(3));
    std::vector<std::unique_ptr<int>> tmpVec;
    std::copy_if(std::make_move_iterator(boxVec.begin()),
                 std::make_move_iterator(boxVec.end()),
                 std::back_inserter(tmpVec),
                 [&](std::unique_ptr<int> const& p){
                     return *p == 17; });
    for (auto const& x: boxVec) {
        (x? std::cout << *x: std::cout << "<null>") << " ";
    }
    std::cout << "\n";
}

取消引用 std::move_iterator&lt;It&gt; 将返回迭代器值类型的合适右值。由于右值是使用std::move(*it) 获得的,所以它是一个参考。也就是说,在实际移动价值之前,价值不会被盗。比较使用const&amp;,即它不会窃取值。该赋值将成为一个右值赋值。该代码还使用std::back_inserter() 来安排足够多的元素进入目的地。

我不认为这真的是一个可靠的解决方案,但我也不认为有像 std::move_if() 这样的算法(或任何算法的定制导致相同的行为)。要真正处理有条件移动的对象,我认为您对传递给谓词的值和分配对象的方式有不同的访问机制(property maps 将解决这些问题,但目前还没有建议将它们添加到C++ 标准)。

【讨论】:

  • 您可以使用remove_copy_if 代替copy_if,这样可以从旧向量中删除移动的元素。
【解决方案2】:

没有直接的方法可以做到这一点,但你可以链接一些 STL 命令来实现你想要的:

  • std::stable_partitionstd::partition 将您的容器分成两半。
  • std::move 将要移动的值移动到新向量中
  • vector.erase 删除旧的、无效的 unique_ptr

最后你有一个干净的源向量(所有移动的无效条目都被删除)和一个干净的目标向量。

这可能看起来像这样:

std::vector<std::unique_ptr<int>> source, target;
// ... fill data
auto it = std::stable_partition(begin(source),end(source),[](std::unique_ptr<int> const& val) {
    return *val < 3; // your negated condition
});
std::move(it,end(source),std::back_inserter(target));
source.erase(it,end(source));

Here is a live example

【讨论】:

    【解决方案3】:

    std::unique_ptr可移动的,而不是可复制的
    因此,您不能将 std::copy_if()unique_ptr 实例一起使用。

    如果你真的想使用std::copy_if(),那么你可以使用std::shared_ptr而不是std::unique_ptr,然后如果你想摆脱旧的矢量内容,只需使用例如销毁它。 vector::clear().

    或者,如果shared_ptr 对您来说开销太大,或者在任何情况下您只需要unique_ptrs 的向量,那么您可能需要考虑使用@987654331 就地删除不需要的向量元素@ 和erase-remove idiom

    【讨论】:

      猜你喜欢
      • 2014-04-02
      • 1970-01-01
      • 1970-01-01
      • 2017-06-12
      • 2021-03-31
      • 2020-04-13
      • 1970-01-01
      • 1970-01-01
      • 2017-11-10
      相关资源
      最近更新 更多