8

I have this:

vector<Object*> myVec;

and adding my objects to it like this:

Object *obj1 = new Object;
myVec.push_back(obj1);

Let's assume that I have 100 objects in this way and pointers going as *obj1, *obj2 ... *obj100.
And now I want to remove let's say, obj37, from the vector. I wish I could do that just like pushing it:

myVec.remove_back(obj37);

It would be awesome if there was a function like "remove_back" but there is not I think. I hope you got the point and please help me about that.

By the way, just look at this question, in accepted answer, there is remove algorithm works by value:

vec.erase(std::remove(vec.begin(), vec.end(), 8), vec.end());

I gave it a shot that with pointer even I didn't believe that would work and surprise; it didn't:

myVec.erase(std::remove(myVec.begin(), myVec.end(), *obj37), vec.end());

Yeah, I know that I've just bullshit but that's for you got the point. Somewhere there should be a simple solution like this and I just want that.

Community
  • 1
  • 1
allyozturk
  • 117
  • 1
  • 1
  • 7
  • 1
    The simple solution is to not manually manage your memory. If you really need pointers, use smart pointers. As you have a collection of pointers, though, if you want to compare the dereferenced pointers rather than the pointers themselves, you'll need to provide your own comparator to `std::remove_if`. – chris Oct 25 '14 at 22:03
  • If you are sure that you need functionality that vector provides to you in your program then I would suggest you to change a data structure from std::vector to std::map. – antonpp Oct 25 '14 at 22:06
  • @chris Yeah, I was using boost shared_ptrs but I've removed them back after reading a nice article. Besides, I just wanna do everything by myself 'cause I'm new at C++ and OOP and believe that this will bring on me better. I will look for `std::remove_if` Thanks. – allyozturk Oct 25 '14 at 22:11

3 Answers3

14

You're almost there: Search the element by value:

myVec.erase(std::remove(myVec.begin(), myVec.end(), obj37), myvec.end());
//                                                  ^^^^^

Alternatively, if you know that the element is in position 36 (0-based), you can erase it directly:

myvec.erase(myvec.begin() + 36);

Or, in modern C++:

myvec.erase(next(begin(myvec), + 36));

Also note that std::remove searches the entire vector, so if you know that there is only one element, you can use find instead to stop as soon as you find the value:

{
    auto it = std::find(myVec.begin(), myVec.end(), obj37);
    if (it != myVec.end()) { myVec.erase(it); }
}
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Oh come ooonn :) I feel so stupid just right now :) How didn't I try that without *? And I can't erase it by position because obj37 was just an assumption I couldn't know the position in my thing. `myVec.erase(std::remove(myVec.begin(), myVec.end(), obj37), myvec.end());` working like a charm. Thank you so much. – allyozturk Oct 25 '14 at 22:30
  • 3
    For those who cannot get this compiled, don't forget to `#include ` – B Faley Jul 02 '17 at 06:43
2

std::remove() "removes" the values matching the last argument. That is, you can remove your pointer like this:

myVec.erase(std::remove(myVec.begin(), myVec.end(), ptr), myVec.end());

If there is just one element matching it may be easier to use std::find() instead of std::remove(). If you actually want to match the pointed to value you'd use the _if version of the algorithm with a suitable predicate. Of course, removing the pointer won't release any memory.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
-1

If you use C++11 you can put smart pointers into your vector. Than you can use the erase-method to remove the object and automaticly the smart pointer handles the delete pointer stuff.

vector<std::shared_ptr<Object>> myVec;

The shared_ptr has a reference rounter inside. If the object is not referenced by any variable it will be delete automaticly.

Mosa
  • 373
  • 1
  • 14