最佳方法是如何使用 std::list 容器与 std::map。

huangapple go评论68阅读模式
英文:

What's the best way to use std::list container with std::map

问题

在C++中创建指向std::list容器的指针是否有效?示例程序似乎工作正常。

#include <iostream>
#include <list>
#include <map>

int main()
{
    std::map<int, std::list<int>*> map_list;

    std::list<int>* my_list = new std::list<int>;
    my_list->push_back(10);
    my_list->push_back(20);

    map_list.emplace(1, my_list);

    for (auto maplist : map_list)
    {
        std::cout<<"KEY:"<<maplist.first<<std::endl;
        std::cout<<"std::list<int>* PTR:"<<maplist.second<<std::endl;

        auto mylist = *(maplist.second);
        for (auto x : mylist)
        {
            std::cout<<"Value:"<<x<<std::endl;
        }
    }

    /*资源释放*/
    for (auto maplist : map_list)
    {
        std::cout<<"KEY:"<<maplist.first<<std::endl;
        std::cout<<"std::list<int>* PTR:"<<maplist.second<<std::endl;

        maplist.second->clear();
        delete maplist.second;
    }
    map_list.clear();
    return 0;
}

我想知道这种做法是否可取,或者我创建std::list容器指针的方式是否有问题。

英文:

Is it valid to create a pointer to an std::list container in C++? The sample program seems to be working fine.

#include &lt;iostream&gt;
#include &lt;list&gt;
#include &lt;map&gt;

int main()
{
    std::map&lt;int, std::list&lt;int&gt;*&gt; map_list;

    std::list&lt;int&gt;* my_list = new std::list&lt;int&gt;;
    my_list-&gt;push_back(10);
    my_list-&gt;push_back(20);

    map_list.emplace(1, my_list);

    for (auto maplist : map_list)
    {
        std::cout&lt;&lt;&quot;KEY:&quot;&lt;&lt;maplist.first&lt;&lt;std::endl;
        std::cout&lt;&lt;&quot;std::list&lt;int&gt;* PTR:&quot;&lt;&lt;maplist.second&lt;&lt;std::endl;

        auto mylist = *(maplist.second);
        for (auto x : mylist)
        {
            std::cout&lt;&lt;&quot;Value:&quot;&lt;&lt;x&lt;&lt;std::endl;
        }
    }

    /*resource release*/
    for (auto maplist : map_list)
    {
        std::cout&lt;&lt;&quot;KEY:&quot;&lt;&lt;maplist.first&lt;&lt;std::endl;
        std::cout&lt;&lt;&quot;std::list&lt;int&gt;* PTR:&quot;&lt;&lt;maplist.second&lt;&lt;std::endl;

        maplist.second-&gt;clear();
        delete maplist.second;
    }
    map_list.clear();
    return 0;
}

I am wondering if this practice is advisable, or if there is anything wrong with the way I am creating a pointer to the std::list container.

答案1

得分: 3

使用原始指针是危险的,很容易泄漏内存。 std::list 转移起来相当便宜,所以你可以直接跳过指针,以大致相同的性能获得相同的基本行为(如果有什么区别,可能会更好一些,因为避免了额外的间接层次):

#include <iostream>
#include <list>
#include <map>

int main()
{
    std::map<int, std::list<int>> map_list;  // 没有指针!

    std::list<int> my_list;  // 没有使用 new
    my_list.push_back(10);   // 没有指针,所以使用 . 而不是 - >

    map_list.emplace(1, std::move(my_list));  // 移动到 map 中,避免复制

    for (const auto& maplist : map_list)  // 引用迭代,避免复制;从不修改,所以使用 const 是好的
    {
        std::cout << "KEY:" << maplist.first << std::endl;

        const auto& mylist = maplist.second;  // 使用引用避免复制
        for (auto x : mylist)  // 这只是整数,所以这里不需要引用
        {
            std::cout << "Value:" << x << std::endl;
        }
    }

    // 完全不需要资源释放;`map` 会自动清理其 RAII 管理的内容
    return 0;
}

节省了所有明确的清理代码,并使用移动语义和引用来避免不必要的复制工作(诚然,在编写的程序中,只有一个长度为2的list,复制许多更大的list比仅引用其内容要昂贵得多,而且没有涉及复制)。

英文:

Using raw pointers is dangerous; makes it too easy to leak memory. std::list is pretty cheap to move though, so you could just skip the pointer and get the same basic behaviors with roughly equivalent performance (if anything, slightly better due to avoiding an extra layer of indirection):

#include &lt;iostream&gt;
#include &lt;list&gt;
#include &lt;map&gt;

int main()
{
    std::map&lt;int, std::list&lt;int&gt;&gt; map_list;  // No pointers!

    std::list&lt;int&gt; my_list;  // No new
    my_list.push_back(10);   // No pointers, so . over -&gt;
    my_list.push_back(20);

    map_list.emplace(1, std::move(my_list));  // Move into map, avoid copy

    for (const auto&amp; maplist : map_list)  // Iterate by reference, avoid copies; never modified, so const is good
    {
        std::cout&lt;&lt;&quot;KEY:&quot;&lt;&lt;maplist.first&lt;&lt;std::endl;

        const auto&amp; mylist = maplist.second;  // Use reference to avoid copy
        for (auto x : mylist)  // It&#39;s just integers so references unnecessary here
        {
            std::cout&lt;&lt;&quot;Value:&quot;&lt;&lt;x&lt;&lt;std::endl;
        }
    }

    // No need for resource release at all; the `map` will clean its RAII managed contents automatically
    return 0;
}

Saves all the explicit code for cleanup, and uses move-semantics and references to avoid unnecessary copy work (admittedly pretty trivial in the program as written, with just one length 2 list, but copying many larger lists would be much more expensive than just referencing their contents, with no copies involved).

huangapple
  • 本文由 发表于 2023年6月16日 08:48:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76486322.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定