C++ C++;如何在迭代时从向量中删除 std::矢量列表; int*a=新的int; *a=3; int*b=新的int; *b=2; int*c=新的int; *c=1; intList.push_back(a); intList。推回(b); intList.push_back(c); std::vector::it迭代器; for(it=intList.begin();it!=intList.end();) { int*a=(int*)*it; 如果((*a)==2) { 删除一条; 删除(它); } 其他的 { ++它; } }
当从向量中删除某些内容时,此代码在for循环开始时崩溃。我不明白为什么。我正在使用Visual Studio 2015,如果这有助于C++ C++;如何在迭代时从向量中删除 std::矢量列表; int*a=新的int; *a=3; int*b=新的int; *b=2; int*c=新的int; *c=1; intList.push_back(a); intList。推回(b); intList.push_back(c); std::vector::it迭代器; for(it=intList.begin();it!=intList.end();) { int*a=(int*)*it; 如果((*a)==2) { 删除一条; 删除(它); } 其他的 { ++它; } },c++,C++,当从向量中删除某些内容时,此代码在for循环开始时崩溃。我不明白为什么。我正在使用Visual Studio 2015,如果这有助于擦除返回下一个迭代器 std::vector<int *>intList; int *a = new int; *a = 3; int *b = new int; *b = 2; int *c = new int; *c = 1; intList.push_back(a); intList.push_back(b); intList.push_back
擦除
返回下一个迭代器
std::vector<int *>intList;
int *a = new int;
*a = 3;
int *b = new int;
*b = 2;
int *c = new int;
*c = 1;
intList.push_back(a);
intList.push_back(b);
intList.push_back(c);
std::vector<int *>::iterator it;
for (it = intList.begin(); it != intList.end();)
{
int *a = (int*)*it;
if ((*a) == 2)
{
delete a;
intList.erase(it);
}
else
{
++it;
}
}
编辑:
remove()
和remove\u if()
将复制元素(此处的指针),其中一个元素将以指向同一整数的多个元素结束,如果您尝试释放它们,将留下悬空的指针
假设向量有4个元素,看起来像
if ((*a) == 2)
{
delete a;
it = intList.erase(it);
}
人们可能会尝试使用erase-remove
习惯用法
0x196c160 0x196bec0 0x196c180 0x196bee0
现在看来
auto temp = remove_if(vec.begin(),vec.end(),[](const auto &i){return *i==2;});
temp
将指向3rd
元素和
0x144aec0 0x144b180 0x144b180 0x144aee0
现在,第二个元素是一个悬空指针
编辑2:
如果在复制元素之前删除
,可以解决上述问题。请查看@Dietmar的答案。删除
返回下一个迭代器
std::vector<int *>intList;
int *a = new int;
*a = 3;
int *b = new int;
*b = 2;
int *c = new int;
*c = 1;
intList.push_back(a);
intList.push_back(b);
intList.push_back(c);
std::vector<int *>::iterator it;
for (it = intList.begin(); it != intList.end();)
{
int *a = (int*)*it;
if ((*a) == 2)
{
delete a;
intList.erase(it);
}
else
{
++it;
}
}
编辑:
remove()
和remove\u if()
将复制元素(此处的指针),其中一个元素将以指向同一整数的多个元素结束,如果您尝试释放它们,将留下悬空的指针
假设向量有4个元素,看起来像
if ((*a) == 2)
{
delete a;
it = intList.erase(it);
}
人们可能会尝试使用erase-remove
习惯用法
0x196c160 0x196bec0 0x196c180 0x196bee0
现在看来
auto temp = remove_if(vec.begin(),vec.end(),[](const auto &i){return *i==2;});
temp
将指向3rd
元素和
0x144aec0 0x144b180 0x144b180 0x144aee0
现在,第二个元素是一个悬空指针
编辑2:
如果在复制元素之前删除,则上述问题可以解决。请查看@Dietmar的答案。该代码导致迭代器无效
您正在删除一个对象,然后期望迭代器(它只是一个指针)知道刚才发生了什么
如果你必须遍历整个向量,那么考虑一个临时的向量来保存/丢弃和使用它。
或者更好的方法是使用find
该代码导致迭代器无效
您正在删除一个对象,然后期望迭代器(它只是一个指针)知道刚才发生了什么
如果你必须遍历整个向量,那么考虑一个临时的向量来保存/丢弃和使用它。
或者更好的方法是使用find
如果您查看一下擦除函数,它将返回下一个迭代器。在您的情况下,使用it=intList.erase(it)
是解决方案。在c++11之后,来自其他容器的所有擦除函数都遵循相同的思想。如果您查看一下擦除函数,它将返回下一个迭代器。在您的情况下,使用it=intList.erase(it)
是解决方案。在c++11之后,其他容器中的所有擦除函数都遵循相同的思想。简单的答案是:你没有!相反,您使用两阶段的方法:首先去掉元素,然后调整容器的大小。使用原始指针会使事情稍微复杂一些,但仍然可行:
for(auto it=temp;it!=vec.end();it++)
delete *it;
在迭代std::vector
时试图擦除单个元素具有非线性的最坏情况复杂性。简单的答案是:你没有!相反,您使用两阶段的方法:首先去掉元素,然后调整容器的大小。使用原始指针会使事情稍微复杂一些,但仍然可行:
for(auto it=temp;it!=vec.end();it++)
delete *it;
在迭代std::vector
时尝试删除单个元素具有非线性的最坏情况复杂性。最好使用std::vector
(如果不需要指针,甚至可以使用std::vector
)
然后只需使用擦除-删除习惯用法:
auto end = std::remove_if(intList.begin(), intList.end(),
[](int *ptr){ return *ptr == 2 && (delete ptr, true); });
intList.erase(end, endList.end());
最后,如果确实需要手动执行此操作,则必须将擦除行修复为:
std::vector<int*> intList{ new int {3}, new int {2}, new int{1} };
auto it = std::partition(intList.begin(), intList.end(),
[](const auto& p){ return *p != 2; });
std::foreach (it, intList.end(), [](int* p) { delete p; });
intList.erase(it, intList.end());
拥有:
it = intList.erase(it);
向量intList{new int{3},new int{2},new int{1};
对于(auto it=intList.begin();it!=intList.end();/*空*/){
int*p=*it;
如果(*p==2){
删除p;
它=intList.erase(它);
}否则{
++它;
}
}
最好使用std::vector
(如果不需要指针,甚至可以使用std::vector
)
然后只需使用擦除-删除习惯用法:
auto end = std::remove_if(intList.begin(), intList.end(),
[](int *ptr){ return *ptr == 2 && (delete ptr, true); });
intList.erase(end, endList.end());
最后,如果确实需要手动执行此操作,则必须将擦除行修复为:
std::vector<int*> intList{ new int {3}, new int {2}, new int{1} };
auto it = std::partition(intList.begin(), intList.end(),
[](const auto& p){ return *p != 2; });
std::foreach (it, intList.end(), [](int* p) { delete p; });
intList.erase(it, intList.end());
拥有:
it = intList.erase(it);
向量intList{new int{3},new int{2},new int{1};
对于(auto it=intList.begin();it!=intList.end();/*空*/){
int*p=*it;
如果(*p==2){
删除p;
它=intList.erase(它);
}否则{
++它;
}
}
这有一种常见的模式,称为。@BoBTFish在这种情况下可能有点过于复杂,需要调用delete
。它认为需要两个过程。为什么不让intList
保持普通int
s而不是指针,然后执行intList.erase(std::remove_if(intList.begin(),intList.end(),[](const auto&elem){return elem==2;}),intList.end()
或intList.erase(std::remove(intList.begin()、intList.end()、2)、intList.end())代码>?可能重复此操作有一个通用模式,称为。@BoBTFish在这种情况下可能有点过于复杂,需要调用delete
。它认为需要两个过程。为什么不让intList
保持普通int
s而不是指针,然后执行intList.erase(std::remove_if(intList.begin(),intList.end(),[](const auto&elem){return elem==2;}),intList.end()
或intList.erase(std::remove(intList.begin()、intList.end()、2)、intList.end())代码>?我更喜欢使用std::partition
和原始指针的可能重复