STD::Vector- write directly to the internal array
Asked Answered
C

2

7

Is the following code ok?:

std::vector<char> var;
size_t requiredSize;

getenv_s(&requiredSize, NULL, 0, "Something");
if (requiredSize == 0)
{
   return ENV_NOT_EXIST;
}
if(var.size() < requiredSize)
    var.resize(requiredSize);

// Get the value of the environment variable.
getenv_s(&requiredSize, &var[0], requiredSize, "Something");

std::string str(var.begin(),var.end());

If this code is OK, can someone please explain me how the begin() and the end() values of the var vector are updated? it looks like this code changes directly the internal array of the vector, not over the std::vector api - so how these values are updated to the actual size?

Convexoconcave answered 12/9, 2013 at 8:52 Comment(3)
Besides the fact that your std::vector magically changes its name from var to svar to var again, yes that's save to do.Ay
In C++11 (and in practice also in C++03) you can do basically the same on std::string, no need for a temporary copy on a vector.Patellate
This is an old one, but I happened across it and looks like somehow no one really answered the initial question of "how the begin() and end() values are updated". It's hiding in plain sight - it's the resize() call.Monroy
M
13

std::vector guarantees data to be stored contiguously, so writing to data, as long as you do not overrun the end is perfectly fine:

From the C++11 standard section 23.3.6.1.1:

The elements of a vector are stored contiguously, meaning that if v is a vector where T is some type other than bool, then it obeys the identity &v[n] == &v[0] + n for all 0 <= n < v.size().

However, note that resizing the vector might move the data and invalidate iterators.

Unfortunately, the standard does not require std::vector<T>::iterator to be a raw pointer type (although it usually is). So, you cannot portably use std::vector<T>::begin() to access the first element. There is std::vector<T>::data(), which returns a pointer to the first element and which can be used for code that expects raw c-arrays.

I suggest to rewrite your call like this:

getenv_s(&requiredSize, var.data(), var.size(), "Something");
if (requiredSize < var.size())
  var.resize(requiredSize);
Michellmichella answered 12/9, 2013 at 8:57 Comment(6)
Before C++03-TC1, the standard guaranteed that data was stored linearly, but not contiguously -- vectors could potentially be padded, and &v.begin()[i] wasn't necessarily the i'th element. In practice, though, all library implementations made this okay.Bluegill
assuming I will use std::vector<char>::data(), how the std::vector aware to the getenv_s changes. lets say getenv_s function failes - it starts to change the &var[0] array, but somehow fails in the middle - how does the vectore.end() know untill when the internal array is changed?Convexoconcave
@RRR: Well, you cannot use the data() member function, because the pointer it returns is const so you cannot write to it (see const-correctness). You can, however just pass &vec[0] as you are doing now, due to the guarantees of (recent) C++ standards regarding the storage of a vector. Regarding "becoming aware": The function getenv_s just writes to the buffer and the data is there. The vector doesn't need to become "aware" of anything.Michellmichella
@bitmask: There are both const and non-const overloads of vector::data() (at least in C++11, but I'm fairly sure that's not new). Perhaps you're thinking of std::string?Willing
@MikeSeymour: Oh boy, I must be blind, I specifically checked my statement by looking at cppreference but some neuron decided not to see the first overload. Thanks for pointing it out!Michellmichella
@RRR: Please see my edit! My statement about std::vector<T>::data() war wrong. Please use var.data() instead of &var[0].Michellmichella
M
2

This is an old one, but I happened across it and looks like somehow no one really answered the initial question of "how the begin() and end() values are updated" when the vector's internal array is manipulated directly. The answer is hiding in plain sight - it's the resize() call.

Monroy answered 28/11, 2023 at 2:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.