C++容器的迭代器失效规则是什么?
优选地以摘要列表格式.
(注意:这是Stack Overflow的C++常见问题解答的一个条目.如果你想批评在这种形式下提供常见问题解答的想法,那么发布所有这些的元数据的发布将是这样做的地方.这个问题在C++聊天室中受到监控,其中FAQ的想法一开始就出现了,所以你的答案很可能被那些提出想法的人阅读.)
如果我在向量上使用.reserve(items),向量将分配足够的内存来猜测我需要的项目数.
如果我以后使用.clear(),那么只清除向量还是保存我之前定义的保留?
谢谢.
我试图修复一些使用向量的代码,并且有一些循环看起来像这样:
for (int t=0;t<T;t++){
std::vector<double> vect;
for (int i=0;i<MAX;i++){
double value;
vect.push_back(value);
}
/*....*/
}
Run Code Online (Sandbox Code Playgroud)
我或多或少知道如何通过重复使用相同的向量进行外部迭代来改进这一点,但在这样做时我发现当调用std::vector::clear "向量容量不能保证改变"时,我实际上希望能够保证容量不要改变 也许我只是误解了cplusplus.com上的内容.但是,我的问题是:
如何在不改变容量的情况下清除矢量?
我应该叫reserve后clear,以确保产能一样吗?
PS:为了清楚,我想重写上面的代码
std::vector<double> vect;
vect.reserve(MAX);
for (int t=0;t<T;t++){
for (int i=0;i<MAX;i++){
double value;
vect.push_back(value);
}
/*....*/
vect.clear();
}
Run Code Online (Sandbox Code Playgroud)
即.我仍然希望填充它push_back,我担心clear()改变矢量的容量.
对于std :: vector的副本分配,当源的大小小于目标的容量时,是否允许重新分配存储和容量缩减?或者是否保证不会发生重新分配/收缩(即始终遵守先前的保留())?
另一方面,如果源的大小大于目的地的容量并且重新分配,则需要重新分配是否与源的容量相关(例如,目的地的新容量应不小于源的容量,或者甚至需要它们是一样的)?或者重新分配只是完成其工作(基于新的大小)而不考虑源的容量?
至于移动分配,我认为不会进行存储重新分配(虽然我未能在标准中找到相关部分),那么它是否意味着目标新容量的值与源的旧容量完全相同?我能期望v = vector<T>{};产生同样的效果vector<T>{}.swap(v);吗?
我想答案都隐藏在标准的某个地方,但我却找不到它们.(如果C++ 11和C++ 03的内容不同,我想知道两者的各种要求.)
PS:对于上述问题的答案,对于std :: string是否相同(仅在C++ 11中,这意味着连续存储而且没有COW,C++ 03字符串不在雷达中)?
我开始比较:
但后来我注意到即使在push_back()deque上似乎也更快.我必须做一些错误的,我不能相信一个更一般的容器也不太可能超过一个特定的一个.
我使用谷歌基准测试的代码:
#include "benchmark/benchmark.h"
#include <deque>
#include <vector>
#define NUM_INS 1000
static void BM_InsertVector(benchmark::State& state) {
std::vector<int> v;
v.reserve(NUM_INS);
while (state.KeepRunning()) {
state.PauseTiming();
v.clear();
state.ResumeTiming();
for (size_t i = 0; i < NUM_INS; i++)
v.push_back(i);
}
}
BENCHMARK(BM_InsertVector);
static void BM_InsertDeque(benchmark::State& state) {
std::deque<int> v;
while (state.KeepRunning()) {
state.PauseTiming();
v.clear();
state.ResumeTiming();
for (size_t i = 0; i < NUM_INS; i++)
v.push_back(i);
}
}
BENCHMARK(BM_InsertDeque);
BENCHMARK_MAIN();
Run Code Online (Sandbox Code Playgroud)
结果:
Run on (1 X 2592 MHz …Run Code Online (Sandbox Code Playgroud) 我正在将许多对象合并到包含渲染数据(网格)的单个向量中.这个向量被清除并重新填充每个帧(好吧,差不多).
问题是,在我的情况下,清除然后再次保留向量大小会对性能产生巨大影响,因为clear()也可能会改变容量.
换句话说,我需要控制向量的容量何时发生变化.我想保留旧容量很长一段时间,直到我决定自己是时候改变它了.
我看到两个选择:
更新
另外,如果调用调整大小(10),然后调用调整大小(5)(仅用于说明,将实际数字乘以数百万),该怎么办?
稍后调用resize(5)会导致向量重新分配吗?
有很多的答案有std::vector,但怎么样std::unordered_set?
我真正的问题(密切相关)是这样的; 如果我事先保留我所知道的合理尺寸,那么在每次使用之前通过清除它来重复使用相同的无序集是否有效?
鉴于a std::vector,其大小和容量可以是任意的,将其大小更改为0并将容量更改为至少N(给定数量)的最佳做法是什么?
我的直接想法是:
void f(vector<int> &t, int N)
{
t.clear();
t.reserve(N);
}
Run Code Online (Sandbox Code Playgroud)
但我注意到了
不能保证重新分配,并且不保证向量容量会改变(当调用std :: vector :: clear时).
所以我想知道当原始容量大于给定的N时,如何避免重新分配?
这个问题以一些代码开始,只是因为我认为更容易看到我所追求的内容:
/*static*/
void
Url::Split
(std::list<std::string> & url
, const std::string& stringUrl
)
{
std::string collector;
collector.reserve(stringUrl.length());
for (auto c : stringUrl)
{
if (PathSeparator == c)
{
url.push_back(collector);
collector.clear(); // Sabotages my optimization with reserve() above!
}
else
{
collector.push_back(c);
}
}
url.push_back(collector);
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,该collector.reserve(stringUrl.length());行应该减少下面循环期间执行的堆操作量。毕竟,每个子字符串不能比整个 url 长,因此像我一样保留足够的容量看起来是个好主意。
但是,一旦子字符串完成并将其添加到 url 部分列表中,我需要以某种方式将字符串重置为长度 0。简短的“查看定义”检查表明,至少在我的平台上,保留的缓冲区将被释放,这样,我的 Reserve() 调用的目的就会受到损害。
_Eos(0)在内部它会在清除的情况下调用一些。
我也可以完成相同的任务,collector.resize(0)但查看定义显示它也在内部调用_Eos(newsize),因此行为与调用 的情况相同clear()。
现在的问题是,是否有一种可移植的方法来建立预期的优化,以及哪个std::string函数可以帮助我实现这一点。
我当然可以写,collector[0] = '\0';但这对我来说看起来很不合适。
旁注:虽然我发现了类似的问题,但我认为这不是其中任何一个的重复。
提前致谢。
当向量的元素被动态分配/是指针时,我所看到的所有问题都是关于管理内存的问题.我的问题只是一个已经在堆栈上分配的向量,例如,一个简单的类型int.
如果我有以下代码:
std::vector<int> vec(5);
for(int i = 0; i < vec.size(); i++) {
std::cout << vec[i] << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我完成后需要打电话clear()吗?
有没有办法std::vector在保留内存分配的同时清除内容?
这样做的原因是我有一段代码循环,我希望优化它。我目前将数据存储在std::vectors 中。每次循环开始时,应清除向量的内容。然后我使用push_back将数据输入到向量中,但是由于向量的长度在循环的迭代之间通常不会改变,我理想情况下希望向量将其分配的存储保留在内存中。
如果这是不可能的,vector是否可以使用另一种快速访问 STD 类型?
我的问题几乎是这个问题的延伸:std :: vector内存是否清除了?
在这里,人们解释说,调用clear()后,不会释放为std :: vector元素分配的内存.但是这个内存对于操作系统来说是免费的,以允许其他程序使用它,还是可以让我的程序在其他任何地方使用它?
如果没有(如果内存继续只分配给这个向量,我不能再访问它)是不是像指针那样的内存泄漏?然后清楚()单独使用时这样会完全不安全吗?
如果有人能在这一点上澄清我,我会很高兴.谢谢.