简体   繁体   中英

Use C++17 features to better delete all pointers from a container

Before C++17, deleting all pointers from a map looked like:

for (TMapBuffOnAttrs::iterator it = m_map_buff_on_attrs.begin();  it != m_map_buff_on_attrs.end(); it++)
{
    if (NULL != it->second)
    {
        delete(it->second);
    }
}
m_map_buff_on_attrs.clear();

With C++17, we got:

for (auto it = m_map_buff_on_attrs.begin();  it != m_map_buff_on_attrs.end(); it++)
{
    if (NULL != it->second)
    {
        delete(it->second);
    }
}

Is there a simpler solution?

Yes.

for (auto it = m_map_buff_on_attrs.begin();  it != m_map_buff_on_attrs.end(); it++)

Since you only use the value *it and no other data from that iterator, a for-range loop would be simpler.

if (NULL != it->second)
{
    delete(it->second);
}

Deleting NULL is well-defined and has no effect, this is a test you can skip.


Which gives:

for (auto& p : m_map_buff_on_attrs) {
    delete p.second;
}

Manipulating raw pointers is error-prone and makes you write more useless code. If m_map_buff_on_attrs were a map of smart pointers, your code would simply be:

} // m_map_buff_on_attrs goes out of scope and destroys and frees everything.

RAII pattern is your friend:

using TMapBuffOnAttrs = std::map<std::string, std::unique_ptr<Attr>>;

m_map_buff_on_attrs["attrName"] = std::make_unique<Attr>(x, a);


....
// loop is not needed, to delete just do:
m_map_buff_on_attrs.clear();

You can use for_each with lambda function.

Here is a way:

std::for_each(m_map_buff_on_attrs.begin(), m_map_buff_on_attrs.end(), 
              [](auto &item) {delete item.second;}); 

Yes, use smartpointers. And simply 'clear()' the container... Otherwise this is just "C code written in C++17"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM