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++;如何在迭代时从向量中删除 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

当从向量中删除某些内容时,此代码在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(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
和原始指针的可能重复