• 0

C++ (STL): remove specific object from list


Question

Hello,

I have learned that I can create a linked list of objects, like this:

list< MyClass* > = myList;

I also know that if it were a list of primitive types, such as a list<int>, I could remove a specific element by calling

remove(myList.begin(), myList.end(), 8);

which for instance would remove any element that is 8.

However let's say MyClass has an attribute name_. I have a list of objects of type MyClass, and I'd like to create a function that finds and removes the object that has that name.

Stub:

void remove(string &name) const

{

remove(myList.begin(), myList.end(), ???);

}

The thing is, if I supply the string &name as an argument to the remove algorithm, it will attempt to compare MyClass objects with strings, which doesn't make sense. What I'd like it to do is compare the name_ attribute of its MyClass objects with the string &name.

I thought of supplying a boolean function that would return element->name_ == name, but the function would need two arguments (list<MyClass*> element, string &name) and I don't think that would work.

As you see I'm stuck.

10 answers to this question

Recommended Posts

  • 0

The way I have done this (which is probably wrong as I taught it to myself) is to use a std::map.

This way you would do something like:

 std::map&lt; std::string name, MyClass* &gt; MyList;
MyList["ClassName"] = PtrToClass;
MyList.erase( the name of the class (the std::name), in this case "ClassName" );

Even if this is wrong hopefully someone can show me how to do it right.

  • 0

for a list:

std::list&lt;MyClass*&gt; MyList

a remove function could be like:

void remove(string &amp;name) const
{
  std::list&lt;MyClass*&gt;::iterator iter;
  for (iter = MyList.begin(); iter != MyList.end(); iter++)
  {
	if ((*iter)-&gt;name_.equalis(name))
	{
	  MyList.erase(iter);
	  break;
	}
  }
}

  • 0

Lant's suggestion is probably the correct one if changing the container is practical which would depend on the particular circumstances.

dev's suggestion is probably the easier (and by no means wrong) if you have to stick with list<>.

The more STL solution would be to use one of the supplied algorithms, in this case remove_if would seem appropriate. The link shows some sample code which uses 'compose1' and 'bind2nd' to construct the 'predicate' function. This is also the STL way of doing things, i.e. you are reusing generic components instead of writing lots of special case code.

If all this 'predicate' stuff is a bit confusing try a different approach. Give your class an overloaded equality operator with another class of the same type which only compares their name_ attribute. Then pass a dummy instance of such a class to remove with the name_ attribute set to the desired value to remove.

As you can gather there are really a load of approaches and this can make C++ seem overwhelming at first. Just remember no one way is necessarily the best. But usually the professionals prefer the solution which reuses existing generic code rather than the individual approach.

  • 0

Ok I'm starting to make some sense of out bind2nd and compose1. Really cool stuff.

Another important question I have about the STL: let's say I have a vector of pointers to dynamic objects, for example:

std::vector< MyClass* > myVector;

MyClass * object1 = new MyClass();

MyClass * object2 = new MyClass();

myVector.push_back(object1);

myVector.push_back(object2);

When I call myVector.clear(), the cplusplus reference says that it will call the destructors for each of the elements. The thing is, I'm not sure if I need to call delete for each of these pointers or not.

  • 0
  Eoin said:
dev's suggestion is probably the easier (and by no means wrong) if you have to stick with list<>.

i tend to go for more verbose code due to me favouring the C way of doing things over C++. Only times i use C++ parts is when i want a list of things and don't want to make my own linked list, or i need classes with subclasses. Most of the time i avoid the STL due it not liking threading very well (in my experience anyway)

  Dr_Asik said:
Ok I'm starting to make some sense of out bind2nd and compose1. Really cool stuff.

Another important question I have about the STL: let's say I have a vector of pointers to dynamic objects, for example:

std::vector< MyClass* > myVector;

MyClass * object1 = new MyClass();

MyClass * object2 = new MyClass();

myVector.push_back(object1);

myVector.push_back(object2);

When I call myVector.clear(), the cplusplus reference says that it will call the destructors for each of the elements. The thing is, I'm not sure if I need to call delete for each of these pointers or not.

afaik you will need to delete the objects, i wasn't aware that calling clear() would call the destructors of the objects but apparently it does (Y)

  • 0
  Dr_Asik said:
When I call myVector.clear(), the cplusplus reference says that it will call the destructors for each of the elements. The thing is, I'm not sure if I need to call delete for each of these pointers or not.

Yeah I think you still need to call delete. I'm pretty sure the destructors only get called for objects stored by value

std::vector< MyClass > myVector;

MyClass object1;

myVector.push_back(object1);

If you need to store them as pointers consider using a smart point like boost::shared_ptr<>.

  • 0

Hm I'm really puzzled at how I am supposed to deallocate memory when erasing specific elements from a list. I thought about using auto_ptr (I can't use boost now), but the cplusplus reference advises against this:

Warning: It is generally a bad idea to put auto_ptr objects inside C++ STL containers. C++ containers can do funny things with the data inside them, including frequent reallocation (when being copied, for instance). Since calling the destructor of an auto_ptr object will free up the memory associated with that object, any C++ container reallocation will cause any auto_ptr objects to become invalid.

http://www.cppreference.com/cppmisc/auto_ptr.html

So what should I do?

  • 0

Well you can still manually call delete whenever you remove a element from a container, but ideally you do want a smart pointer to do this automatically.

If Boost IS an option then use shared_ptr as I suggested or the pointer containers. Or if you have access to tr1 the tr1::shared_ptr is the boost::shared_ptr basicially.

Otherwise you could try finding another reference counted smart pointer. The problem is inside STL containers objects can get copied as the container grows so if you used auto_ptr then at times there could exist two auto_ptr's to the same object. You need to use a reference counted smart pointer in this case as it ensures the object is deleted only when there are no smart pointers left pointing to it.

I know Scott Meyers published a reference counted smart pointer. Haven't used it myself but I imagine it should work fine. Of course it's published in one of his books but maybe you can find a listing of the code if you look around his online articles. His site maintains a list.

Others surely exist out there too but ideally you should use the boost or tr1 shared_ptr if you can.

  • 0

Well, as I really have to stick to absolute basic stuff, the STL, and not use any sort of loops, I have developped a very heavy and unelegant solution. Basically I selectively copy the elements that must not be removed into a new container. But as the containers contain pointers to these elements, I have to really copy objects, a costly process. Then I call delete on every pointer of the old container, erase the container, and assign the new container to the old container. Then the new container is discarded.

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • Vivaldi 7.4.3684.52 by Razvan Serea Vivaldi is a cross-platform web browser built for – and with – the web. A browser based on the Blink engine (same in Chrome and Chromium) that is fast, but also a browser that is rich in functionality, highly flexible and puts the user first. A browser that is made for you. Vivaldi is produced with love by a founding team of browser pioneers, including former CEO Jon Stephenson von Tetzchner, who co-founded and led Opera Software. Vivaldi’s interface is very customizable. Vivaldi combines simplicity and fashion to create a basic, highly customizable interface that provides everything a internet user could need. The browser allows users to customize the appearance of UI elements such as background color, overall theme, address bar and tab positioning, and start pages. Vivaldi features the ability to "stack" and "tile" tabs, annotate web pages, add notes to bookmarks and much more. Vivaldi 7.4.3684.52 changelog: [Address bar] URL is searched instead of opening (VB-117198) [Chromium] Update to 136.0.7103.179 [Settings][Workspaces] Add Workspace Rule button hidden by 4th rule (VB-117181) Download: Vivaldi 64-bit | 125.0 MB (Freeware) Download: Vivaldi 32-bit | ARM64 View: Vivaldi Home Page | Screenshot Get alerted to all of our Software updates on Twitter at @NeowinSoftware
    • NTLite 2025.06.10482 by Razvan Serea NTLite is a Windows configuration tool that allows you to modify your existing Windows install or an image yet to be deployed, remove Windows components, configure and integrate, speed up the Windows deployment process. Reduce Windows footprint on your RAM and storage drive memory. Remove components of your choice, guarded by compatibility safety mechanisms, which speed up finding that sweet spot. Windows Unattended feature support, providing many commonly used options on a single page for easy setup. Easily integrate a single or multiple drivers, update or language packages. Package integration features smart sorting, enabling you to seamlessly add packages for integration and the tool will apply them in the appropriate order, keeping hotfix compatibility in check. One of the important new features of NTLite (compared to its predecessors) is the ability to modify an already installed the operating system, by removing unnecessary components. Supports Windows 11, 10, 8.1 and 7, x86 and x64, live and image. Server editions of the same versions, excluding support for component removals and feature configuration. ARM64 image support in the alpha stage. Does not support Checked/Debug, Embedded, IoT editions, nor Vista or XP. NTLite 2025.06.10482 changelog: Fix Image: Image optimization would be skipped if both boot.wim and install.wim would keep only one edition Image: Crash after exporting unloaded image in certain situations Upgrade UI-Translation: Thanks for Turkish (Salih DURDU), Georgian (Anonymous) Download: NTLite 64-bit | 21.5 MB (Free, paid upgrade available) Download: NTLite 32-bit | 19.3 MB Link: NTLite Home Page | NTLite Features | Screenshot Get alerted to all of our Software updates on Twitter at @NeowinSoftware
    • CrystalDiskMark 9.0.1 is out.
    • Wonder if the HDMI Forum will allow AMD to use HDMI 2.2 under Linux.
    • Where did you hear visio is discontinued? It's still available and being updated on Office 365 and even has an online free version now too.. and dont tell me because visio 2021 has EOL listed a Oct 13, 2026.. they have a beta version right now for visio 2026
  • Recent Achievements

    • Week One Done
      Wayne Robinson earned a badge
      Week One Done
    • One Month Later
      Karan Khanna earned a badge
      One Month Later
    • Week One Done
      Karan Khanna earned a badge
      Week One Done
    • First Post
      MikeK13 earned a badge
      First Post
    • Week One Done
      OHI Accounting earned a badge
      Week One Done
  • Popular Contributors

    1. 1
      +primortal
      690
    2. 2
      ATLien_0
      264
    3. 3
      Michael Scrip
      201
    4. 4
      +FloatingFatMan
      167
    5. 5
      Steven P.
      138
  • Tell a friend

    Love Neowin? Tell a friend!