从向量中提取子向量而不复制

18

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

类似于:

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) 
{
   .... 
}
我想要的是获得 {3, 5, 6, 8} 作为 dest,但它要指向原始数据而不是新副本。 (索引是从原始向量中提取数据的索引向量)
或者,我能用智能指针来做到这一点吗?

2
指针的问题在于一旦矢量调整大小,它们就会失效。 - Borgleader
1
一个向量是一个连续存储元素的容器;你想要的似乎与它不兼容。 - Kerrek SB
3个回答

6
您无法从另一个std::vector<T>的子范围创建std::vector<T>。但是,您可以通过使用视图来遍历存储在拥有实际值的std::vector<T>中的迭代器:
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<T>,但还要存储std::shared_ptr<std::vector<T>>作为基础表示(如果需要修改原始表示,则存储偏移量而不是迭代器)。


6

每次我说我已经放弃使用 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

valarray 看起来非常有趣!相关问题将其与 vector 进行了比较:https://dev59.com/cXI-5IYBdhLWcg3w8dUQ - Jonathan Lidbeck

3
如果你想让向量可变,那么不行。如果你只是想传递一个子向量但不改变其内容,为什么不将各种函数更改为使用起始和结束迭代器而不是传递向量呢?

我没有找到一种使用迭代器的起始和结束来从非连续索引的向量中提取元素的方法。你能给一个简单的例子吗? - duqiyaner
不,列表中间有空隙是行不通的。你可以尝试一些变化,比如保留起始/结束迭代器对的列表,但我真的不建议在没有充分理由的情况下增加这种复杂性。 - Gabe Sechan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接