• 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

    • They probably mean File Pilot, which this colorful rainbow program can never compete with, because this WinUI crap isn’t made for apps like that. My advice? You should just switch the framework already
    • Scientists uncover bizarre new material that's breaking one of the laws of this Universe by Sayan Sen Image by Ron Lach via Pexels Scientists from the University of Chicago and UC San Diego have discovered a group of materials that behave in surprising ways when put under heat, pressure or electricity. Instead of responding like most materials, these can shrink when heated, expand when compressed, and even bounce back to their original state with the right electric charge. The work focuses on oxygen-redox (OR) materials—types that can help batteries store more energy but typically suffer from stability problems due to structural disorder. In their normal state, the materials follow the usual rules of thermodynamics. But in what's called a “metastable” state, a kind of temporary balance, they behave in reverse. “When heated, the material shrinks instead of expanding,” said Prof. Shirley Meng, senior author of the study published in Nature. This is linked to what’s known as a disorder–order transition inside the material’s structure. The team recorded a negative thermal expansion rate of −14.4(2) × 10⁻⁶ °C⁻¹, which means the material actually contracts when warmed up. This goes against a common theory called the Grüneisen relationship, which usually explains why materials expand with heat. And pressure? Even stranger. When they pushed the material on all sides at levels seen in Earth's tectonic plates, it expanded instead of getting smaller. “Negative compressibility is just like negative thermal expansion,” explained Prof. Minghao Zhang. “If you compress a particle of the material in every direction… it will expand.” They also found that electricity can reset the material’s structure. By tweaking the voltage limits, they recovered almost 100% of the original structure and performance. This has big potential for battery tech, especially electric vehicles (EVs). “When we use the voltage, we drive the material back to its pristine state. We recover the battery,” said Zhang. He added: “You just do this voltage activation… your car will be a new car. Your battery will be a new battery.” The research may lead to materials with zero thermal expansion, helpful in everything from buildings to aircraft. Zhang noted, “Take every single building, for example. You don't want the materials making up different components to change volume that often.” As they move forward, the team wants to understand how redox chemistry can further control these effects and expand practical uses. “One of the goals is bringing these materials from research to industry,” said co-first author Bao Qiu. Their work opens up a new way of thinking about material design, where energy doesn’t just power devices, but reshapes the building blocks themselves. Source: University of Chicago, Nature This article was generated with some help from AI and reviewed by an editor. Under Section 107 of the Copyright Act 1976, this material is used for the purpose of news reporting. Fair use is a use permitted by copyright statute that might otherwise be infringing.
    • "Elon Musk says a kid-friendly 'Baby Grok' is on the way" No kid wants to be a baby anymore. "Kid friendly" I would have named it "Kid Grok"
    • TP-Link Tri-Band AXE5400 Wi-Fi 6E Gaming Router Archer GXE75 is just $135 by Sayan Sen If you’re juggling gaming consoles, 4K streams and a growing roster of smart devices, the TP-Link Archer GXE75 Tri-Band AXE5400 Wi-Fi 6E Gaming Router is a good option to look at right now, considering the device is currently on sale at just $135 (purchase link under the specs table below). The Archer GXE75 promises up to 5.4 Gbps of throughput across three bands: 574 Mbps on 2.4 GHz, 2402 Mbps on 5 GHz and 2402 Mbps on 6 GHz (HE160 channels enabled). A 2.5 Gbps WAN/LAN port pairs with three 1 Gbps LAN ports and a USB 3.0 port for fast file sharing or printer access (purchase link down below). The quad-core CPU and 512 MB of RAM should help to handle multiple streams without bogging down, while MU-MIMO, OFDMA and 1024-QAM improve efficiency when several devices connect simultaneously. The router’s built-in Game Accelerator engine is said to automatically prioritize gaming packets (both wired and wireless), and TP-Link’s GPN (Gamers Private Network) acceleration can reduce packet loss for supported titles. HomeShield security brings firewall protection, device quarantining and parental controls. The technical specifications of the router are given below: Specification Details Wireless Standards IEEE 802.11ax 6 GHz; IEEE 802.11ax/ac/n/a 5 GHz; IEEE 802.11ax/n/g/b 2.4 GHz Wi-Fi Speeds 6 GHz: 2402 Mbps (802.11ax); 5 GHz: 2402 Mbps (802.11ax); 2.4 GHz: 574 Mbps (802.11ax) Spatial Streams 6 streams (tri-band OFDMA/MU-MIMO) Processor 1.7 GHz 64-bit Quad-Core CPU Memory 512 MB high-speed RAM Ethernet Ports 1× 2.5 Gbps WAN/LAN; 1× 1 Gbps WAN/LAN; 3× 1 Gbps LAN USB 1× USB 3.0 SuperSpeed port (up to 10× faster than USB 2.0) Antennas 4× high-performance external antennas with Beamforming Buttons Power On/Off; Reset; WPS/Wi-Fi; LED On/Off Working Modes Router Mode; Access Point Mode Security WPA, WPA2, WPA3, WPA/WPA2-Enterprise; SPI firewall; Access Control; IP/MAC binding; Application-layer gateway; HomeShield security suite VPN OpenVPN, PPTP, L2TP (server & client); WireGuard (server & client) Software & Services IPv4/IPv6; TP-Link HomeShield; EasyMesh; Parental controls; QoS by device; WAN types (Dynamic IP, Static IP, PPPoE, PPTP, L2TP); DDNS (TP-Link, NO-IP, DynDNS); auto firmware updates Gaming Features Game QoS boost; gaming-port priority; Gamers Private Network acceleration; game-port forwarding; real-time game panel with stats & RGB control Operating Environment 0 °C – 40 °C; 10 %– 90 % non-condensing humidity Get the TP-Link Tri-Band AXE5400 Wi-Fi 6E Gaming Router Archer GXE75 at the link below: TP-Link Tri-Band AXE5400 Wi-Fi 6E Gaming Router Archer GXE75 | EasyMesh, HomeShield: $159.99 + $25 off with coupon => $134.99 (Sold and Shipped by Amazon US This Amazon deal is US-specific and not available in other regions unless specified. If you don't like it or want to look at more options, check out the Amazon US deals page here. Get Prime (SNAP), Prime Video, Audible Plus or Kindle / Music Unlimited. Free for 30 days. As an Amazon Associate, we earn from qualifying purchases.
  • Recent Achievements

    • Rookie
      Snake Doc went up a rank
      Rookie
    • First Post
      nobody9 earned a badge
      First Post
    • One Month Later
      Ricky Chan earned a badge
      One Month Later
    • First Post
      leoniDAM earned a badge
      First Post
    • Reacting Well
      Ian_ earned a badge
      Reacting Well
  • Popular Contributors

    1. 1
      +primortal
      495
    2. 2
      Michael Scrip
      203
    3. 3
      ATLien_0
      197
    4. 4
      Xenon
      137
    5. 5
      +FloatingFatMan
      116
  • Tell a friend

    Love Neowin? Tell a friend!