std functions to replace range of bytes in vector
Asked Answered
R

4

6

I have a vector of bytes (std::vector ): [1,1,1,9,9,9,1,1,1]

I want to replace bytes 3-6 with unknown length of bytes (I'll know at run time obv.). So the length of the vector may grow, shirk or stay the same. But I know the start point and end point of the bytes I want to replace.

I can do this using erase or insert to adjust the size, then a loop around the new data onto the old data.

std::replace does a search and the replaces matching the bytes, whereas I know what bytes I want to replace. And std::replace seem to only replace one element. I want to replace with blob of data.

Surely there is a std function that can do this 'neatly'? (and I'll call you Shirely if I want to).

Reflation answered 13/3, 2017 at 11:50 Comment(1)
How much do you know at compile time? Do you know the original contents of the vector? Or least its size? Or at least the range you need to remove before inserting?Seng
T
5

If the values are all the same and you know the interval you want to replace is within the vector, use std::fill:

std::fill(v.begin() + 3, v.begin() + 6, 9);

This line will replace elements 3-6 on the vector v with value 9.

If the values you want to put are not all the same, use std::copy instead (you need to be sure that the replacement fits into the vector):

std::copy(replacement.begin(), replacement.end(), v.begin() + 3); 

This replaces contents of the vector v starting at position 3 with contents of replacement.

If you are not sure about the size of the vector, you may correct the size first:

v.resize(6);
Tornado answered 13/3, 2017 at 12:58 Comment(1)
Changing a range within a vector was my use case. This was the exact answer I needed. Thanks!Ashcraft
E
3

std::vector::insert can insert ranges, so just erase the existing elements and insert the new ones.

Elijaheliminate answered 13/3, 2017 at 11:54 Comment(3)
Yes. My first thought. I just would like to be more efficient. And not delete space that I might need afterwards. Save a lot of data moving about.Reflation
You could do a combination of std::copy (to copy the portion of the range that overlaps with what's in the vector already) and either erase or insert (to adjust the vector's size appropriately).Spheroidicity
Do in two steps, (1) insert or erase elements to make the final length correct (2) copy the elements that were not copied at step 1.Shenitashenk
D
1

Short answer: there's no ultimate solution for your problem unless we get more details from you

Long answer: From what I see here, it sounds to me that std::vector is a very bad choice for this. std::vector is contiguous in memory (starting from C++03), and what you're doing has two possible outcomes:

  1. You'll keep the same size of the container, and vectors are perfect for this
  2. You'll change the size of the vector from the middle, and vector's are horrible at this! But, std::deque is a middle grounds for this. The reason for this is here. It exactly supports doing what you want to do in (almost) constant time, and provides element access at constant time.

The question you need to answer to decide which way to go is: How often do you need to make a replacement that will change the size of the vector compared to one that won't? Only if the number changes in the size of the vector are very small, std::vector would be a good choice. Otherwise, you should consider switching to std::deque.

Is there something in the standard that does that replacement for me?

The standard provides all the tools to do this as efficient as possible with a function that you write yourself. Erase (if necessary), then insert. It's as simple as that. Keep in mind two things:

  1. Erase only the difference, don't erase the whole thing you want to replace, the former would perform better
  2. Always consider the special case if the part you want to remove has a size equal to the array you want to place in. In that case, don't remove or insert anything. This saves a lot in performance.
Dellinger answered 13/3, 2017 at 12:16 Comment(0)
E
0

It's a vector, so anything you do which might alter its size is going to require possibly allocating another contiguous block of memory. I would recommend, instead of always erasing then inserting, to either erase, insert or do nothing based on the length of the replacement. If the replacement is shorter than the original range, then erase the extra ones from the original range, if it's longer, then insert next to the original range and if it's the same size, then do nothing. After that, you can simply copy the new values into the new range. You should make sure the old elements are destroyed if they are not trivially destructible, though.

Enlargement answered 17/6 at 20:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.