容器元素为指针时,删除元素的问题

时间:2022-09-03 14:03:51
A* a = new A;
A* b = new B;
vector<A* > v;
v.push_back(a);
v.push_back(b);
for(vector<A*>::iterator it = v.begin();it != v.end();++it)
{
  if(*it == b)
  {
     delete *it;
     v.erase(it);
  }
}
这样删除一个指针元素可行吗?

28 个解决方案

#1


可以

#2


可以

#3


同意一楼二楼意见。

#4


问题是delete *it后,*it已不存在,再v.erase(it),it所指的内容都没了,erase(it)会正常吗?这里面好像有问题。

#5


引用 4 楼 aatny1 的回复:
问题是delete *it后,*it已不存在,再v.erase(it),it所指的内容都没了,erase(it)会正常吗?这里面好像有问题。


是指针指向的内容没有的,但是指针还在的,内容是指针,可以的。没有问题。

#6


引用 4 楼 aatny1 的回复:
问题是delete *it后,*it已不存在,再v.erase(it),it所指的内容都没了,erase(it)会正常吗?这里面好像有问题。

没关系。因为你保存的是指针。delete并没有修改指针本身,他仅仅是释放了指针指向的那块资源。

#7


这段代码在dev-cpp上测试,出现了内存访问违例,i.e. 这段代码有问题!
测试了另一种方法,正常:
vector<A*>::iterator it = v.begin();
for(vector<A*>::size_type i = 0;i < v.size();i++)
{
   if(v[i] == b)
   {
      delete v[i];
      v.erase(it);
   }
   ++it;
}

#8


谁能说说前一种方法出现异常是为什么吗?如果按你们的说法,是不会出现异常的。

#9


正在学习容器,学习了

#10


UP。。。。

#11


for(vector <A*>::iterator it = v.begin();it != v.end();++it) 

  if(*it == b) 
  { 
    delete *it;     //delete的是A*指针指向的内存
    v.erase(it);    //erase的是删除指向A*的指针所存用的内存。
  } 


可以的,这跟2维数组的动态删除是一样的。

#12


for(vector <A*>::iterator it = v.begin();it != v.end();++it) 

  if(*it == b) 
  { 
    delete *it;     //delete的是A*指针指向的内存
    v.erase(it);    //erase的是删除指向A*的指针所存用的内存。
  } 


可以的,这跟2维数组的动态删除是一样的。

#13



A* a = new A; 
A* b = new A; 
vector <A* > v; 
v.push_back(a); 
v.push_back(b); 
for(vector <A*>::iterator it = v.begin();it != v.end();) 

  if(*it == b) 
  { 
    delete *it; 
    it=v.erase(it); 
  } else
  ++it;


如楼上的我运行错误,感觉v.erase(it)后在++可是删除的时候迭代器不是失效了吗?还可以++吗?感觉删除的时候应该重新定义迭代器的位置才对!

#14


引用 7 楼 aatny1 的回复:
这段代码在dev-cpp上测试,出现了内存访问违例,i.e. 这段代码有问题! 


把你测试的完整代码贴出来看看!!!这么用事没问题的

#15


呃,竟然没有人看过《effective stl》item9的?

#16


引用 13 楼 s79947171 的回复:
C/C++ code
A* a = new A; 
A* b = new A; 
vector <A* > v; 
v.push_back(a); 
v.push_back(b); 
for(vector <A*>::iterator it = v.begin();it != v.end();) 

  if(*it == b) 
  { 
    delete *it; 
    it=v.erase(it); 
  } else
      ++it;

如楼上的我运行错误,感觉v.erase(it)后在++可是删除的时候迭代器不是失效了吗?还可以++吗?感觉删除的时候应该重新定义迭代器的位置才对!



iterator erase ( iterator position );

Return value
A random access iterator pointing to the new location of the element that followed the last element erased by the function call, which is the vector end if the operation erased the last element in the sequence.

删除后是要重新定义迭代器的位置的。

#17


强烈建议楼主不要这么写,if you erase an iterator, that iterator gets a so-called singular value, which means it doesn't belong to any container anymore. You can't increment, decrement or read it out/write to it anymore. 
也就是说,你删除以后要该iterator不属于该stl容器,不能进行加减操作了
你可以改成
A* a = new A; 
A* b = new B; 
vector <A* > v; 
v.push_back(a); 
v.push_back(b); 
for(vector <A*>::iterator it = v.begin();it != v.end();) 

  if(*it == b) 
  { 
    delete *it; 
    v.erase(it++); 
  } 
  else
   ++it;

#18


学习了

#19


作为一个谨慎的策略,建议楼主用下标吧。

#20


好的方法应该只是释放内存,而不是改变容器的大小。这样效率低又容易出错。

#21


引用 13 楼 s79947171 的回复:
C/C++ code
A* a = new A; 
A* b = new A; 
vector <A* > v; 
v.push_back(a); 
v.push_back(b); 
for(vector <A*>::iterator it = v.begin();it != v.end();) 

  if(*it == b) 
  { 
    delete *it; 
    it=v.erase(it); 
  } else
      ++it;




如楼上的我运行错误,感觉v.erase(it)后在++可是删除的时候迭代器不是失效了吗?还可以++吗?感觉删除的时候应该重新定义迭代器的位置才对!


此答案正解,erase之后获得的是你下一个iterator,这个操作是必要的,不然会出现内存失效。

#22


#23


顺次找到b之后,删除之,然后再次循环(因为it没有到达 end,再次运行到
 if(*it == b)
的时候会出问题的,因为it++在else里,但上次删除被执行,但++没有执行,再次*it的时候存在违规了。

引用 21 楼 biosli 的回复:
引用 13 楼 s79947171 的回复:
C/C++ code 
A* a = new A; 
A* b = new A; 
vector <A* > v; 
v.push_back(a); 
v.push_back(b); 
for(vector <A*>::iterator it = v.begin();it != v.end();) 

  if(*it == b) 
  { 
    delete *it; 
    it=v.erase(it); 
  } else 
      ++it; 

#24


1. 肯定你的做法,可以
2. 推荐做法 自己做一层薄的封装 或者直接用 boost的 share_ptr<>,
   注意,auto_ptr是不能用于容器的

#25


引用楼主 aatny1 的帖子:
A* a = new A;
A* b = new B;
vector <A* > v;
v.push_back(a);
v.push_back(b);
for(vector <A*>::iterator it = v.begin();it != v.end();++it)
{
if(*it == b)
{
delete *it;
v.erase(it);
}
}
这样删除一个指针元素可行吗?

不够严谨! 正确的做法如下并加有注释

for(vector <A*>::iterator it = v.begin();it != v.end();++it)
{
if(*it == b)
{
delete *it;
v.erase(it); // 当你删除最后一个元素时,it 已等于尾指针
if(it==v.end()) 
break;  // 此时要终止循环,否则 ++it 后,it!=v.end() 永远成立
}                      // 指针成为野指针,访问指针所指内容时出现运行期错误。


#26


感谢大家的关注和帮忙。CSDN上热心人真多!
分值有限,无法分配的十分公正。

#27


引用 25 楼 hejinjing_tom_com 的回复:
这样删除一个指针元素可行吗?

不够严谨! 正确的做法如下并加有注释
C/C++ code
for(vector::iterator it = v.begin();it != v.end();++it)
{
if(*it == b)
{
delete *it;
v.erase(it); // 当你删除最后一个元素时,it 已等于尾指针
if(it==v.end()) 
break;  // 此时要终止循环,否则 ++it 后,it!=v.end() 永远成立
}                      // 指针成为野指针,访问指针所指内容时出现运行期错误。
}


测试一下,确实是这样的!
但是set不能这样用。仍然出现野指针错误,实验过了。

#28


引用 25 楼 hejinjing_tom_com 的回复:
引用楼主 aatny1 的帖子:
A* a = new A;
A* b = new B;
vector <A* > v;
v.push_back(a);
v.push_back(b);
for(vector <A*>::iterator it = v.begin();it != v.end();++it)
{
if(*it == b)
{
delete *it;
v.eras……

这个代码我在VS 2005还是不能通过,首先不说编译的问题,你这个逻辑就是有错误的
v.erase(it)被执行以后,获得的是你下一个iterator,与it++一个道理,然后再for循环中又++it相当于被加了2才次
如果vector中存在这样的数据[数据是我模拟的]12,12,123,456而12是你要删除的数据,你只能删除第一个12

#1


可以

#2


可以

#3


同意一楼二楼意见。

#4


问题是delete *it后,*it已不存在,再v.erase(it),it所指的内容都没了,erase(it)会正常吗?这里面好像有问题。

#5


引用 4 楼 aatny1 的回复:
问题是delete *it后,*it已不存在,再v.erase(it),it所指的内容都没了,erase(it)会正常吗?这里面好像有问题。


是指针指向的内容没有的,但是指针还在的,内容是指针,可以的。没有问题。

#6


引用 4 楼 aatny1 的回复:
问题是delete *it后,*it已不存在,再v.erase(it),it所指的内容都没了,erase(it)会正常吗?这里面好像有问题。

没关系。因为你保存的是指针。delete并没有修改指针本身,他仅仅是释放了指针指向的那块资源。

#7


这段代码在dev-cpp上测试,出现了内存访问违例,i.e. 这段代码有问题!
测试了另一种方法,正常:
vector<A*>::iterator it = v.begin();
for(vector<A*>::size_type i = 0;i < v.size();i++)
{
   if(v[i] == b)
   {
      delete v[i];
      v.erase(it);
   }
   ++it;
}

#8


谁能说说前一种方法出现异常是为什么吗?如果按你们的说法,是不会出现异常的。

#9


正在学习容器,学习了

#10


UP。。。。

#11


for(vector <A*>::iterator it = v.begin();it != v.end();++it) 

  if(*it == b) 
  { 
    delete *it;     //delete的是A*指针指向的内存
    v.erase(it);    //erase的是删除指向A*的指针所存用的内存。
  } 


可以的,这跟2维数组的动态删除是一样的。

#12


for(vector <A*>::iterator it = v.begin();it != v.end();++it) 

  if(*it == b) 
  { 
    delete *it;     //delete的是A*指针指向的内存
    v.erase(it);    //erase的是删除指向A*的指针所存用的内存。
  } 


可以的,这跟2维数组的动态删除是一样的。

#13



A* a = new A; 
A* b = new A; 
vector <A* > v; 
v.push_back(a); 
v.push_back(b); 
for(vector <A*>::iterator it = v.begin();it != v.end();) 

  if(*it == b) 
  { 
    delete *it; 
    it=v.erase(it); 
  } else
  ++it;


如楼上的我运行错误,感觉v.erase(it)后在++可是删除的时候迭代器不是失效了吗?还可以++吗?感觉删除的时候应该重新定义迭代器的位置才对!

#14


引用 7 楼 aatny1 的回复:
这段代码在dev-cpp上测试,出现了内存访问违例,i.e. 这段代码有问题! 


把你测试的完整代码贴出来看看!!!这么用事没问题的

#15


呃,竟然没有人看过《effective stl》item9的?

#16


引用 13 楼 s79947171 的回复:
C/C++ code
A* a = new A; 
A* b = new A; 
vector <A* > v; 
v.push_back(a); 
v.push_back(b); 
for(vector <A*>::iterator it = v.begin();it != v.end();) 

  if(*it == b) 
  { 
    delete *it; 
    it=v.erase(it); 
  } else
      ++it;

如楼上的我运行错误,感觉v.erase(it)后在++可是删除的时候迭代器不是失效了吗?还可以++吗?感觉删除的时候应该重新定义迭代器的位置才对!



iterator erase ( iterator position );

Return value
A random access iterator pointing to the new location of the element that followed the last element erased by the function call, which is the vector end if the operation erased the last element in the sequence.

删除后是要重新定义迭代器的位置的。

#17


强烈建议楼主不要这么写,if you erase an iterator, that iterator gets a so-called singular value, which means it doesn't belong to any container anymore. You can't increment, decrement or read it out/write to it anymore. 
也就是说,你删除以后要该iterator不属于该stl容器,不能进行加减操作了
你可以改成
A* a = new A; 
A* b = new B; 
vector <A* > v; 
v.push_back(a); 
v.push_back(b); 
for(vector <A*>::iterator it = v.begin();it != v.end();) 

  if(*it == b) 
  { 
    delete *it; 
    v.erase(it++); 
  } 
  else
   ++it;

#18


学习了

#19


作为一个谨慎的策略,建议楼主用下标吧。

#20


好的方法应该只是释放内存,而不是改变容器的大小。这样效率低又容易出错。

#21


引用 13 楼 s79947171 的回复:
C/C++ code
A* a = new A; 
A* b = new A; 
vector <A* > v; 
v.push_back(a); 
v.push_back(b); 
for(vector <A*>::iterator it = v.begin();it != v.end();) 

  if(*it == b) 
  { 
    delete *it; 
    it=v.erase(it); 
  } else
      ++it;




如楼上的我运行错误,感觉v.erase(it)后在++可是删除的时候迭代器不是失效了吗?还可以++吗?感觉删除的时候应该重新定义迭代器的位置才对!


此答案正解,erase之后获得的是你下一个iterator,这个操作是必要的,不然会出现内存失效。

#22


#23


顺次找到b之后,删除之,然后再次循环(因为it没有到达 end,再次运行到
 if(*it == b)
的时候会出问题的,因为it++在else里,但上次删除被执行,但++没有执行,再次*it的时候存在违规了。

引用 21 楼 biosli 的回复:
引用 13 楼 s79947171 的回复:
C/C++ code 
A* a = new A; 
A* b = new A; 
vector <A* > v; 
v.push_back(a); 
v.push_back(b); 
for(vector <A*>::iterator it = v.begin();it != v.end();) 

  if(*it == b) 
  { 
    delete *it; 
    it=v.erase(it); 
  } else 
      ++it; 

#24


1. 肯定你的做法,可以
2. 推荐做法 自己做一层薄的封装 或者直接用 boost的 share_ptr<>,
   注意,auto_ptr是不能用于容器的

#25


引用楼主 aatny1 的帖子:
A* a = new A;
A* b = new B;
vector <A* > v;
v.push_back(a);
v.push_back(b);
for(vector <A*>::iterator it = v.begin();it != v.end();++it)
{
if(*it == b)
{
delete *it;
v.erase(it);
}
}
这样删除一个指针元素可行吗?

不够严谨! 正确的做法如下并加有注释

for(vector <A*>::iterator it = v.begin();it != v.end();++it)
{
if(*it == b)
{
delete *it;
v.erase(it); // 当你删除最后一个元素时,it 已等于尾指针
if(it==v.end()) 
break;  // 此时要终止循环,否则 ++it 后,it!=v.end() 永远成立
}                      // 指针成为野指针,访问指针所指内容时出现运行期错误。


#26


感谢大家的关注和帮忙。CSDN上热心人真多!
分值有限,无法分配的十分公正。

#27


引用 25 楼 hejinjing_tom_com 的回复:
这样删除一个指针元素可行吗?

不够严谨! 正确的做法如下并加有注释
C/C++ code
for(vector::iterator it = v.begin();it != v.end();++it)
{
if(*it == b)
{
delete *it;
v.erase(it); // 当你删除最后一个元素时,it 已等于尾指针
if(it==v.end()) 
break;  // 此时要终止循环,否则 ++it 后,it!=v.end() 永远成立
}                      // 指针成为野指针,访问指针所指内容时出现运行期错误。
}


测试一下,确实是这样的!
但是set不能这样用。仍然出现野指针错误,实验过了。

#28


引用 25 楼 hejinjing_tom_com 的回复:
引用楼主 aatny1 的帖子:
A* a = new A;
A* b = new B;
vector <A* > v;
v.push_back(a);
v.push_back(b);
for(vector <A*>::iterator it = v.begin();it != v.end();++it)
{
if(*it == b)
{
delete *it;
v.eras……

这个代码我在VS 2005还是不能通过,首先不说编译的问题,你这个逻辑就是有错误的
v.erase(it)被执行以后,获得的是你下一个iterator,与it++一个道理,然后再for循环中又++it相当于被加了2才次
如果vector中存在这样的数据[数据是我模拟的]12,12,123,456而12是你要删除的数据,你只能删除第一个12