【问题标题】:Can I create a view on a vector?我可以在矢量上创建视图吗?
【发布时间】:2020-01-12 12:19:34
【问题描述】:

我有一个函数需要对给定的元素进行排序。原始向量不得更改,因此我需要向量的浅表副本。 由于我不需要复制元素本身,因为它们只是被读取的,所以我决定制作一个指针向量。 目前我有一个简单的循环填充向量,但我想知道是否存在甚至可能更快的内置/标准解决方案。

void calcFindMinLeftAndSort(std::vector<Location>& locationsComplete, std::vector<Location*>& locationsSorted) {
    // ...

    // copy data in new array, to keep the original untouched
    locationsSorted.reserve(locationsComplete.size());
    // looking for locationsSorted.assign(&elements)
    // yes, I could use for each instead
    for (size_t i = 0; i < locationsComplete.size(); i++)
        locationsSorted.emplace_back(&locationsComplete[i]);

    // sort 
    std::sort(locationsSorted.begin(), locationsSorted.end(), compare);
}

附加信息: locationsComplete 向量按特定顺序排序,不得更改。该向量在应用程序运行期间永远不会更改。 排序后的位置排序向量被另一个函数消耗一次(可以在同一个函数中使用,但那样看起来更清晰)。在返回下一个函数的结果后,locationSorted 向量将被淘汰。因此,它可以被视为一个非常短暂的临时向量。

【问题讨论】:

  • 使用该解决方案,您需要注意对原始容器进行任何导致其大小调整的操作都会使第二个(已排序)容器中的指针无效。
  • 与存储指针相比,存储排序索引会更紧凑

标签: c++ c++11 vector


【解决方案1】:

您可以做的,并且可能想要做的是,根本不使用指针 - 只需将索引集排序到 locationsCompare 中,比较函数会在原始区域中查找值。轻松使用 C++11:

template <typename T>
std::vector<size_t> get_sorted_positions(const std::vector<T> &v)
{
  std::vector<size_t> indices(v.size());

  std::iota(indices.begin(), indices.end(), 0); // indices now holds 0 ... v.size()-1
  std::sort(indices.begin(), indices.end(),
       [&v](size_t i_1, size_t i_2) { return v[i_1] < v[i_2]; }
  );

  return indices;
}

注意事项:

  • 唯一发生变异的数据是索引
  • 不用担心返回长向量;由于称为NRVO 的优化,编译器将使用移动构造函数。
  • 这段代码大部分来自this answer,但方法基本上是民间传说。
  • 您可能还想抽象出您的输入是一个向量这一事实,并只引用一个任意容器(并返回std::vector&lt;typename Container::size_type&gt;);或采用一对迭代器;或在 C++20 中 - 取任意范围。

【讨论】:

  • 正如我指出的“不得更改原始向量”。有趣的概念。
  • @GunnarBernstein:原始向量没有被改变,einpoklum 只是在做查找。 (通过 const 引用,这有助于防止修改)
  • @GunnarBernstein:本说了什么。
【解决方案2】:

不得更改原始向量。

考虑通过生成一个指向 const 的非欠指针向量来强制执行此约束

template <class Container>
auto make_vector_of_const_pointers(Container& c)
{
    std::vector<typename Container::const_pointer> result;
    result.reserve(c.size());
    std::generate_n(std::back_inserter(result), c.size(),
                    [it = c.cbegin()]() mutable { return &(*(it++)); });
    return result;
}

见,例如here 一个用法示例,与非 const 版本相比。

【讨论】:

  • 这个 const 可能是出于“安全”原因,不改变原始向量。我没有看到短期功能使用的好处。不是我的问题。
猜你喜欢
  • 2011-03-29
  • 1970-01-01
  • 2021-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-18
相关资源
最近更新 更多