I am trying to copy a series of std::string_view
s into a std::vector<char>
container, without causing additional memory allocation.
I thought that using std::copy
would be the most straightforward approach.
auto buffer = std::vector<char>();
buffer.reserve(1024);
{
const auto line = std::string_view("Content-Type: application/json\r\n");
std::copy(line.begin(), line.end(), buffer.end());
}
{
const auto line = std::string_view("Content-Length: 200\r\n");
std::copy(line.begin(), line.end(), buffer.end());
}
In case it is not obvious, in each of the two above cases where std::copy
is used, I am trying to copy the entire contents of line
into buffer
. The destination address should be the end of buffer
.
However, this code is nonsensical.
It copies zero bytes of data. Having thought about it for a bit, I'm actually not sure exactly why this is the case. Initially I thought that it was because std::copy
was checking the output iterator to ensure it remains in bound. However, I'm not sure how an iterator returned by buffer.end()
would know whether or not it is in bounds or not. (Since this iterator does not have access to the other data members of buffer
.) It was a silly thought...
To summarize:
- I'm not sure why this doesn't work (why are zero bytes of data copied?)
- This is probably not the right approach to the problem. What should I be doing instead?
By the way the intention behind using buffer.reserve
was to avoid allocation.
Of course, one simple way to avoid an allocation would be to check the size of the source and remaining space in the destination first.
I am trying to copy a series of std::string_view
s into a std::vector<char>
container, without causing additional memory allocation.
I thought that using std::copy
would be the most straightforward approach.
auto buffer = std::vector<char>();
buffer.reserve(1024);
{
const auto line = std::string_view("Content-Type: application/json\r\n");
std::copy(line.begin(), line.end(), buffer.end());
}
{
const auto line = std::string_view("Content-Length: 200\r\n");
std::copy(line.begin(), line.end(), buffer.end());
}
In case it is not obvious, in each of the two above cases where std::copy
is used, I am trying to copy the entire contents of line
into buffer
. The destination address should be the end of buffer
.
However, this code is nonsensical.
It copies zero bytes of data. Having thought about it for a bit, I'm actually not sure exactly why this is the case. Initially I thought that it was because std::copy
was checking the output iterator to ensure it remains in bound. However, I'm not sure how an iterator returned by buffer.end()
would know whether or not it is in bounds or not. (Since this iterator does not have access to the other data members of buffer
.) It was a silly thought...
To summarize:
- I'm not sure why this doesn't work (why are zero bytes of data copied?)
- This is probably not the right approach to the problem. What should I be doing instead?
By the way the intention behind using buffer.reserve
was to avoid allocation.
Of course, one simple way to avoid an allocation would be to check the size of the source and remaining space in the destination first.
Share Improve this question edited Mar 14 at 11:49 user2138149 asked Mar 14 at 11:33 user2138149user2138149 17.7k30 gold badges149 silver badges296 bronze badges 3 |1 Answer
Reset to default 4why are zero bytes of data copied?
Because you are dereferencing an iterator that is invalid to dereference. buffer.end()
is approximately a char*
that points one beyond the current last element. Writing past that, even only into the allocated char
s (because you reserve
d some), doesn't change the size()
reported by the buffer.
If you have C++23, then this is very simple:
buffer.append_range(line);
To use std::copy
, you would need to pass an iterator that inserted into the container, rather than one that just pointed to an element.
std::copy(line.begin(), line.end(), std::back_inserter(buffer));
std::ranges::copy(line, std::back_inserter(buffer));
buffer.insert(buffer.end(), line.begin(), line.end());
– Raffallo Commented Mar 14 at 11:37-fsanitize=address
or-fsanitize=undefined
when in doubt. It'll save you from a lot of grief. – Passer By Commented Mar 14 at 11:42