我可以在矢量上创建视图吗?

时间:2019-09-10 17:43:59

标签: c++ c++11 vector

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

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向量被另一个函数使用了一次(可以在同一函数中使用,但这种方式看起来更清晰)。返回下一个函数的结果后,locationsSorted向量将退役。因此,它可以看作是寿命很短的临时向量。

2 个答案:

答案 0 :(得分:4)

您可以做的并且可能想做的是根本不使用指针-只需将索引集排序为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的优化,编译器将使用move构造函数。
  • 此代码主要是从this answer提起的,但是这种方法基本上是民间传说。
  • 您可能还想抽象出输入是向量的事实,只引用一个任意容器(并返回std::vector<typename Container::size_type>);或采用一对迭代器;或在C ++ 20中-取任意范围。

答案 1 :(得分: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版本相比的用法示例。

相关问题