6

Hello I have a vector:

vector<int> myCuteVector {1,2,3,4};

Now I would like to create a subvector in such a way, that it would contain 2 first elements from myCuteVector in such a way that after modifying subvectors elements, elements of myCuteVector would change too.

Pseudo code:

vector<int> myCuteVector {1,2,3,4};
vector<int> myCuteSubVector = myCuteVector[0:2];
myCuteSubVector[0] = 5;
printf("%d", myCuteVector[0]) //would print also 5;

is it possible to achieve?

Jakub Balicki
  • 180
  • 1
  • 11

3 Answers3

7

You can do this with a std::reference_wrapper. That would look like:

int main()
{
    std::vector<int> myCuteVector {1,2,3,4};
    std::vector<std::reference_wrapper<int>> myCuteSubVector{myCuteVector.begin(), myCuteVector.begin() + 2};
    myCuteSubVector[0].get() = 5; // use get() to get a reference
    printf("%d", myCuteVector[0]); //will print 5;
}

Or you could just use iterators directly like

int main()
{
    std::vector<int> myCuteVector {1,2,3,4};
    std::vector<std::vector<int>::iterator> myCuteSubVector{myCuteVector.begin(), myCuteVector.begin() + 1};
    // it is important to note that in the constructor above we are building a list of
    // iterators, not using the range constructor like the first example
    *myCuteSubVector[0] = 5; // use * to get a reference
    printf("%d", myCuteVector[0]); //will print 5;
}
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • Thanks for the answer :D I wonder if I will be able to pull out the size of the subvectors without additional variables in these methods. Is it possible? – Jakub Balicki Mar 18 '20 at 13:33
  • @JakubBalicki Not exactly sure what you mean but `myCuteSubVector.size()` will give you the size of the sub vector. – NathanOliver Mar 18 '20 at 13:35
  • 1
    @JakubBalicki Really though if you are implementing sorting algorithms you don't want to do any of this. What you want is either to use iterator ranges (basically pointers) or pass the main vector by reference, and then pass the start and end indices of the sub vector. Doing this is going to add a bunch of memory allocations and extra data which will hamper performance. – NathanOliver Mar 18 '20 at 13:37
  • in the second method it still prints the size of 4. In the first method I get an error "incomplete type is not allowed" in the myCuteSubVector[0].get() = 5; line – Jakub Balicki Mar 18 '20 at 13:37
  • 1
    @JakubBalicki [Works just fine here](http://coliru.stacked-crooked.com/a/331608323206f502) – NathanOliver Mar 18 '20 at 13:41
  • Ok I was missing one lib, sorry for silly question :) – Jakub Balicki Mar 18 '20 at 13:45
  • @JakubBalicki No problem, glad to help. – NathanOliver Mar 18 '20 at 13:49
  • one more question, is my assumption correct that using span instead of iterator ranges in implementing sorting algorithms wouldn't hamper performance? – Jakub Balicki Mar 18 '20 at 13:59
  • 1
    @JakubBalicki Using span would be a great replacement for iterator ranges. Only reason I didn't suggest it is because C++20 hasn't officially come out yet so support is still limitied. This code will work with a C++11 compliant compiler so it is "more portable" (more systems it can be used on without upgrading the system). If you can use `span`, you should try it out. – NathanOliver Mar 18 '20 at 14:02
5

Since C++20, you can use std::span:

std::vector<int> myCuteVector {1,2,3,4};
std::span<int> myCuteSubVector(myCuteVector.begin(), 2);
myCuteSubVector[0] = 5;
std::cout << myCuteVector[0];  // prints out 5

Live demo: https://wandbox.org/permlink/4lkxHLQO7lCq01eC.

Daniel Langr
  • 22,196
  • 3
  • 50
  • 93
  • 1
    But I just read here [link](https://stackoverflow.com/questions/45723819/what-is-a-span-and-when-should-i-use-one) that **It never allocates nor deallocates anything**. Learned something new, Thanks... – EReload Mar 18 '20 at 13:44
1

You can use pointers: -

vector<int> myCuteVector = {1,2,3,4};
vector<int*> myCuteSubVector;
for(int i = startPos; i < endPos; ++i)
    myCuteSubVector.emplace_back(&myCuteVector[i]);    //or you can use push_back()

Where startPos and endPos(excluding) specifies the indices from the original array which you want to change...

Then, to change value at position 'j'(which should be between [startPos, endPos)) with respect to the original array: -

*myCuteSubVector[j - startPos] = 123;

Of course, in your very specific case, you can simply write like this: -

vector<int> myCuteVector = {1,2,3,4};
vector<int*> myCuteSubVector = {&myCuteVector[0], &myCuteVector[1]};
*myCuteSubVector[0] = 5;

Not sure though why you would want to do this...

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
EReload
  • 199
  • 2
  • 12
  • I'm trying to implement merge and quick sort in cpp in bunch of different ways. So now I'm messing around with vectors :D Thanks for the idea ^^ – Jakub Balicki Mar 18 '20 at 13:32