英文:
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 <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;
}
}
/*resource release*/
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;
}
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 <iostream>
#include <list>
#include <map>
int main()
{
std::map<int, std::list<int>> map_list; // No pointers!
std::list<int> my_list; // No new
my_list.push_back(10); // No pointers, so . over ->
my_list.push_back(20);
map_list.emplace(1, std::move(my_list)); // Move into map, avoid copy
for (const auto& maplist : map_list) // Iterate by reference, avoid copies; never modified, so const is good
{
std::cout<<"KEY:"<<maplist.first<<std::endl;
const auto& mylist = maplist.second; // Use reference to avoid copy
for (auto x : mylist) // It's just integers so references unnecessary here
{
std::cout<<"Value:"<<x<<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 list
s would be much more expensive than just referencing their contents, with no copies involved).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论