18

I have a large size of vector and I want extract its subvector based on index. But I do not want to make a new copy of a subvector. Can I use pointer a iterator to return the pointer of the original vector?

something like:

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) 
{
   .... 
}

What I want get is get dest as { 3,5,6,8 } and it is point to orig but not the new copy. (index is the index vector of what I want to extract from the original vector)

Or, can I use smart pointer to do this?

duqiyaner
  • 181
  • 1
  • 1
  • 4

3 Answers3

6

You won't be able to create a std::vector<T> from a subrange of another std::vector<T>. However, you could travel in terms of a view which stores iterators into a std::vector<T> which is owning the actual values:

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]; }
};

Things get a bit interesting if you want to deal with the same type independently of who owns the actual array. In that case you might want to create something like the array_view<T> above but also storing a std::shared_ptr<std::vector<T>> for the underlying representation (and if you need to modify the original representation, you'd store offsets instead of iterators).

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
6

Every time I say I've sworn off std::valarray, somebody brings up a problem like this that valarray supports quite directly. For example:

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;

Then if (for example) we print out the elements of orig with code like this:

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

... we get the following results:

0       1       2       -1      4       -1      -1      7       -1      9
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • `valarray` looks pretty interesting! Related question comparing it with `vector`: https://stackoverflow.com/questions/1602451/c-valarray-vs-vector – Jonathan Lidbeck Feb 14 '18 at 18:12
3

If you want the vector to be mutable, no. If you just want to pass a subvector around but not change the contents, why not change your various functions to take a start and end iterator rather than be passed a vector?

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
  • I didn't find a way to use iterator start and end to extract from the vector with non-continuously index. Cna you show a simple example? – duqiyaner May 26 '15 at 21:34
  • No, it won't work with a gap in the list. You could do a variation on that where you keep lists of start/end iterator pairs, but I really wouldn't suggest that level of complexity without a really good reason. – Gabe Sechan May 26 '15 at 22:21