【问题标题】:Extract a subvector from a vector without copy从没有复制的向量中提取子向量
【发布时间】:2015-05-27 06:10:17
【问题描述】:

我有一个很大的向量,我想根据索引提取它的子向量。但我不想制作子向量的新副本。 可以使用指针迭代器返回原向量的指针吗?

类似:

vector<int> orig = { 0,1,2,3,4,5,6,7,8,9 };
vector<int> index = { 3,5,6,8 };
vector<int> dest (vector<int> orig, vector<int> index) 
{
   .... 
}

我想要得到的是将 dest 设置为 { 3,5,6,8 } 并且它指向原始副本而不是新副本。 (index是我要从原始向量中提取的索引向量)

或者,我可以使用智能指针吗?

【问题讨论】:

  • 指针的问题是一旦向量调整大小它们就会失效。
  • 向量是一个连续存储的元素容器;你想要的似乎与那个不兼容。

标签: c++ iterator shared-ptr smart-pointers


【解决方案1】:

每次我说我宣誓退出std::valarray,都会有人提出类似valarray 非常直接支持的问题。例如:

std::valarray<int> orig = { 0,1,2,3,4,5,6,7,8,9 };
std::valarray<size_t> index = { 3,5,6,8 };

orig[index] = -1;

那么如果(例如)我们用这样的代码打印出orig 的元素:

for (int i=0; i<orig.size(); i++)
    std::cout << orig[i] << "\t";

...我们得到以下结果:

0       1       2       -1      4       -1      -1      7       -1      9

【讨论】:

【解决方案2】:

您将无法从另一个 std::vector&lt;T&gt; 的子范围创建 std::vector&lt;T&gt;。但是,您可以根据将迭代器存储到拥有实际值的 std::vector&lt;T&gt; 的视图进行旅行:

template <typename Iterator>
class array_view {
    Iterator begin_;
    Iterator end_;
public:
    // ...
    array_view(Iterator begin, Iterator end): begin_(begin), end_(end) {}
    Iterator begin() const { return this->begin_; }
    Iterator end() const   { return this->end_; }
    typename std::iterator_traits<Iterator>::reference
    operator[](std::size_t index) { return this->begin_[index]; }
};

如果您想独立于谁拥有实际数组来处理相同的类型,事情会变得有点有趣。在这种情况下,您可能想要创建类似于上面的 array_view&lt;T&gt; 的东西,但还要为底层表示存储 std::shared_ptr&lt;std::vector&lt;T&gt;&gt;(如果您需要修改原始表示,您将存储偏移量而不是迭代器)。

【讨论】:

    【解决方案3】:

    如果你希望向量是可变的,不。如果你只是想传递一个子向量而不改变内容,为什么不改变你的各种函数来获取一个开始和结束迭代器而不是传递一个向量呢?

    【讨论】:

    • 我没有找到使用迭代器开始和结束从具有非连续索引的向量中提取的方法。你能举个简单的例子吗?
    • 不,它不适用于列表中的空白。您可以在保留开始/结束迭代器对列表的地方做一个变体,但如果没有充分的理由,我真的不会建议这种复杂程度。
    猜你喜欢
    • 2015-11-01
    • 1970-01-01
    • 2010-09-30
    • 2019-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-19
    相关资源
    最近更新 更多