STD::Vector- 直接向内部数组写入

7
以下代码是否可行?
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());

如果这段代码没有问题,能有人给我解释一下var向量的begin()end()值如何被更新吗?看起来这段代码直接修改了向量的内部数组,而不是通过std::vector api进行操作——那么这些值如何被更新为实际大小呢?

1
除了您的 std::vector 神奇地从 var 变成 svar 再变回 var 的事实之外,是的,这样做是安全的。 - nikolas
在C++11中(实际上也适用于C++03),您可以对std::string执行基本相同的操作,无需在vector上进行临时复制。 - sbabbi
这是一个老问题,但我偶然发现似乎没有人真正回答最初的问题:“如何更新begin()和end()的值”。它就藏在那里 - 就是resize()调用。 - undefined
2个回答

11

std::vector保证数据连续存储,因此只要不超过末尾,对数据进行写入是完全可以的:

根据C++11标准第23.3.6.1.1节:

向量的元素是连续存储的,这意味着如果v是一个T类型(除bool外)的向量,则对于所有0 <= n < v.size(),它遵循身份&v[n] == &v[0] + n。

但是,请注意,调整向量的大小可能会移动数据并使迭代器失效。

不幸的是,标准没有要求std::vector<T>::iterator是原始指针类型(尽管通常是这样)。因此,您不能可移植地使用std::vector<T>::begin()来访问第一个元素。有std::vector<T>::data(),它返回指向第一个元素的指针,并且可以用于期望原始c数组的代码。

我建议按照以下方式重写您的调用:

getenv_s(&requiredSize, var.data(), var.size(), "Something");
if (requiredSize < var.size())
  var.resize(requiredSize);

在 C++03-TC1 之前,标准保证数据是线性存储的,但不一定是连续的 -- 向量可能会被填充,&v.begin()[i] 不一定是第 i 个元素。然而,在实践中,所有库实现都能够处理这种情况。 - Sneftel
假设我将使用std::vector<char>::data(),那么std::vector如何知道getenv_s的更改。比方说getenv_s函数失败了-它开始更改&var[0]数组,但在中途某个地方失败了-如何知道vector.end()需要更新到哪里才能反映内部数组的更改? - RRR
@RRR:嗯,你不能使用data()成员函数,因为它返回的指针是const,所以你不能对其进行写操作(请参阅const-correctness)。但是,由于(最近的)C++标准保证了vector的存储,所以你可以像现在这样只传递&vec[0]。关于“意识到”:函数getenv_s只是将数据写入缓冲区,数据就在那里。向量不需要“意识到”任何事情。 - bitmask
1
@bitmask:vector::data()const和非const两种重载形式(至少在C++11中是这样,但我相当确定这不是新的)。也许你想到的是std::string - Mike Seymour
@MikeSeymour:哇喔,我得太瞎了,我明明是通过查看cppreference来检查我的语句的,但是一些神经元决定忽略掉第一个过载。谢谢你指出来! - bitmask
@RRR:请看我的编辑!我关于std::vector<T>::data()的说法是错误的。请使用var.data()而不是&var[0] - bitmask

0
这是一个老问题,但我偶然遇到它,似乎没有人真正回答过最初的问题:“当直接操作向量的内部数组时,如何更新begin()和end()的值”。答案就在眼前 - 就是resize()调用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接