std :: map是C ++标准库中的一个类。它是一个已排序的关联容器,包含具有唯一键的键值对。搜索,删除和插入操作具有对数复杂性。地图通常实现为红黑树。
我们可以通过提供提示来优化 `std::map::find` 的性能吗?
方法 std::map::emplace_hint 允许我们通过提供一个“提示”迭代器来优化 std::map::emplace 的性能,我们希望它非常接近项目所在的位置...
给定一个(非开始())起始键,有没有办法在地图中找到下一个键?
我有一个 std::map 用于实现解释语言的符号表。这正在替换仅使用打包字符串的旧实现...
使用 std::map::at 时对 std::map 的调用不匹配
我遇到了 std::map 函数的问题。 简而言之,我的代码由一个模板基类组成,在该类中,我有一个如下所示的结构: 模板 类基础 {
给定一个包含成对的 std::string,A 的 std::map,其中 A 是一个对象,它生成并管理它自己的线程。 在地图中存在其他元素时插入地图是否存在危险? IE。那个...
为 gcc 编译器设置 std::map.end() 的哨兵值
这里我特别只关心GCC编译器和运行时代码效率。 考虑下面的代码试试我 #包括 #包括 char 查找(const std::map 这里我特别只关心GCC编译器和运行时代码效率。 考虑以下代码试试我 #include <iostream> #include <map> char Find(const std::map<int, char>& map, int key) { auto iter = map.find(key); if (iter == map.end()) return 'X'; return iter->second; } char Find2(const std::map<int, char>& map, int key) { return map.find(key)->second; } int main() { // part 1 std::map<int, char> x{{0,'0'}, {4,'4'}}; std::cout << Find(x, 3) << std::endl; std::cout << Find(x, 4) << std::endl; std::cout << (int)Find2(x, 3) << std::endl; // returns 0 std::cout << Find2(x, 4) << std::endl; // part 2: Find2 is a shortcut std::map<int, char> y(x); y.end()->second = 'X'; std::cout << Find2(y, 3) << std::endl; std::cout << Find2(y, 4) << std::endl; } 第 2 部分也适用于我在 Godbolt 中测试的 GCC 编译器,尽管它以一种奇怪的方式使用 end()。 在GCC中,map是否会分配一个节点std::pair来表示结束?添加/删除元素时它会发生变化吗?这关系到地图的end()是如何真正实现的,我很想知道。 正如许多人指出的那样,如果 end() 被取消引用,C++ 标准将其定义为 UB。 但是,根据this answer,GCC 似乎以 end() 指向根节点的方式实现了映射。有了这个,我认为在这里将根节点的值设置为 X 似乎是一个有效的操作。这是否意味着上面的代码应该适用于 GCC? 由于我阅读了几篇STL容器的GCC实现,所以我对end()哨兵是如何实现的有了一定的了解。 由于问题涉及如何为 end() 容器实现 std::map,因此我将处理它,尽管这个想法适用于几乎所有基于 STL 节点的容器。 大部分 std::map 接口与其他关联容器一样,是 _Rb_tree 对象的包装器,该对象在 stl_tree.h 文件中实现,部分在 tree.tcc 文件中实现。正是在头文件中,可以找到基本节点_Rb_tree_node_base和节点_Rb_tree_node的实现。该节点是基节点的派生类,其中添加了存储成员。准确地说,从 C++11 开始,存储成员不再是 T 类型,而是使用 GCC 版本的 std::aligned_storage 类型定义。 诀窍是使用基本节点的实例作为哨兵节点,它既代表最后一个元素(根据定义,哨兵节点是一个专门设计的节点,用作路径遍历终止符)又代表最后一个元素。在第一个元素之前。本质上,哨兵节点被解释为最后一个元素之后的元素和第一个元素之前的元素。 GCC 实现设计了 std::map 的哨兵节点,以便分别使用其指向父元素、左子元素和右子元素的指针来跟踪根元素、最左边元素和最右边元素。 原来的实现如下: _Base_ptr& _M_root() _GLIBCXX_NOEXCEPT { return this->_M_impl._M_header._M_parent; } _Base_ptr& _M_leftmost() _GLIBCXX_NOEXCEPT { return this->_M_impl._M_header._M_left; } _Base_ptr& _M_rightmost() _GLIBCXX_NOEXCEPT { return this->_M_impl._M_header._M_right; } _M_header成员就是哨兵节点。对于基于节点的容器使用这种方法有几个优点,但是std::forward_list,主要好处有以下两个: 由于 end() 迭代器直接指向哨兵节点,因此它不是悬空指针,即使容器为空也不会表现出特定行为 - 在这种情况下,begin() 和 end() 都指同一个事物,哨兵节点; 由于哨兵节点既用于表示倒数最后一个元素,又用于表示倒数第一元素之前,因此在开始之前和结束之后总会有一个有效节点,然后可以进行插入、擦除和拼接操作在任何位置都以同样的方式进行。 此实现的一个很好的副作用是,如果迭代器 end() 递增,它将落在容器的开头。如前所述,std::forward_list 容器不具有其他基于节点的容器的相同功能,因为它的哨兵节点不正确地仅表示由 before_begin() 迭代器指向的第一个元素,并且 std::nullptr 用于表示最后一个元素。然后,如果 before_begin() 迭代器递增,它将落在序列的开头,但如果 end() 迭代器递增,它将导致 UB。 对于所有其他基于节点的容器,例如std::list,以下代码始终有效: std::list<int> l{0, 1, 2, 3, 4, 5, 6}; auto it{l.cend()}; if(++it == l.cbegin()) std::cout << "Wow!\n"; 你可能已经猜到尝试引用 end() 迭代器是 UB。
我正在为我的应用程序构建命令 shell。我的问题在于在识别映射命令时调用成员函数。 这个 shell 的一个完整而紧凑的例子是 #包括 我正在为我的应用程序构建命令 shell。我的问题在于在识别映射命令时调用成员函数。 这个壳的一个完整和紧凑的例子是 #include <iostream> #include <string> #include <iostream> #include <vector> #include <map> #include <functional> typedef std::vector<std::string> token_list ; class CommandShell { public: CommandShell() {} void runShell(std::ostream& out, std::istream& in); void cmdSave(std::ostream& out, token_list); void cmdLoad(std::ostream& out, token_list); private: //--- important application config values stored here and modified // by user commands in the shell }; void CommandShell::cmdSave(std::ostream& out, token_list) { out << "we're in the save function\n"; } void CommandShell::cmdLoad(std::ostream& out, token_list) { out << "we're in the load function\n"; } void CommandShell::runShell(std::ostream& out, std::istream& in) { //--- create the command/function map typedef void (CommandShell::*userCommand)(std::ostream&, std::vector<std::string>&); std::map<std::string, userCommand> cmd_map; cmd_map.emplace("save", std::mem_fn(&CommandShell::cmdSave)); cmd_map.emplace("load", std::mem_fn(&CommandShell::cmdLoad)); token_list command_and_options; // created by parsing the whole input string std::string cmd_line = ""; while (true) { in >> cmd_line; // tokenize the line here -- simplified for this example command_and_options.push_back(cmd_line); command_and_options.push_back("option1"); if (command_and_options[0] == "quit") { break; } else { auto this_command = cmd_map.find(command_and_options[0]); if (this_command == cmd_map.end()) { std::cout << "unrecognized command!\n"; } else { //--- COMPILATION ERRORS here // I've tried this... std::invoke((*this_command).second, this, std::cout, command_and_options); // and this... std::invoke(this_command->second, this, std::cout, command_and_options); // and this... // (which actually works if I don't use member functions in the map) (*this_command).second(std::cout, command_and_options); } } } } int main() { CommandShell my_shell; my_shell.runShell(std::cout, std::cin); } 我相信我接近正确的语法,因为如果我使用独立函数(不是成员函数),调用函数指针的最后一个版本将起作用。请帮我调整和理解。 您可以使用std::function和std::bind来自<functional>。创建命令名称到处理函数的映射: std::map<std::string, std::function<void(std::ostream&, token_list)>> commands; commands.emplace("save", std::bind(&CommandShell::cmdSave, this, std::placeholders::_1, std::placeholders::_2)); commands.emplace("load", std::bind(&CommandShell::cmdLoad, this, std::placeholders::_1, std::placeholders::_2)); 然后,调用函数: std::string cmd_name = "save"; auto cmd = commands.find(cmd_name); if (cmd == commands.end()) std::cout << "unknown command!"; else cmd->second(std::cout, command_and_options); 你需要告诉 C++ 在哪个实例上调用成员函数,即使对于 this 显然也是如此: (this->*(this_command->second))(std::cout, command_and_options); ^^^^^^^^ ^ 但是,您还有其他编译器错误http://coliru.stacked-crooked.com/a/60a9a8481bd5ff98 您在地图中存储的类型与您在地图中实际放置的类型不匹配。 您的地图包含指向成员的原始指针,但您正试图将 std::mem_fn 返回的对象放置到地图中。这些是不同的东西,而且是不相容的。你需要选择一个。 要么让你的地图包含原始void (CommandShell::*)(std::ostream&, token_list)指向成员的指针并使用指向成员的调用语法调用它们: using userCommand = void (CommandShell::*)(std::ostream&, token_list); std::map<std::string, userCommand> cmd_map; cmd_map.emplace("save", &CommandShell::cmdSave); cmd_map.emplace("load", &CommandShell::cmdLoad); // ... (this->*(this_command->second))(out, command_and_options); 演示 或者让您的地图包含 std::function 对象并使用像 std::mem_fn、std::bind 或 lambda 的包装对象并使用“正常”调用语法: using userCommand = std::function<void(CommandShell*, std::ostream&, token_list)>; std::map<std::string, userCommand> cmd_map; cmd_map.emplace("save", std::mem_fn(&CommandShell::cmdSave)); cmd_map.emplace("load", std::mem_fn(&CommandShell::cmdLoad)); // ... this_command->second(this, out, command_and_options); 演示
无法从 <brace-enclosed initializer list> 转换为 std::map
我被困在一个问题上,我知道这里已经发布了一些类似的问题,但是我还没有能够根据他们的回答解决问题。有人可以帮我吗...
Insert in std::map without default empty constructor
我有 std::map 的实例,我可以在其中插入和填充数据。类 Foo 是默认可构造的,默认可复制的。然后我用这种(简单的)方式来做: 标准::地图 我有 std::map<std::string,Foo> 的实例,我可以在其中插入和填充数据。 Foo 类是默认可构造的,默认可复制的。然后我用这种(简单的)方式来做: std::map<std::string,Foo> data; for(std::string const& key : keys) { assert(data.count(key) == 0); // it's assumed that the keys not already exist Foo& foo = data[key]; foo.fill(blahblah); } 重构后,类Foo失去了默认的空构造函数。 插入和填充的(简单)替代方法是什么data?目前,我用这个代替但我不知道这是否是重构代码的最佳/更简单的方法: std::map<std::string,Foo> data; for(std::string const& key : keys) { assert(data.count(key) == 0); // it's assumed that the keys not already exist Foo& foo = data.emplace(key, Foo(requirement)).first->second; foo.fill(blahblah); } 我也认为 insert, insert_or_assign, emplace, emplace_hint, try_emplace 是可能的。我有点迷失了所有的可能性...... 我对 C++11 或 C++17 的解决方案感兴趣。 从这里 调用此函数等同于: (*((this->insert(make_pair(k,mapped_type()))).first)). 因此,在这种情况下,operator[] 的文字替换将使用 insert 函数。但是,我建议使用 emplace 以避免额外构造 std::pair,insert 函数接受作为参数。 自 C++17 起,您可以使用 try_emplace 除非非常微妙的情况。您可以参考 this discussion 以查看是否更喜欢 emplace 而不是 try_emplace 适用于您的情况。 您可以将 std::map::emplace 与 std::make_pair 和 std::move 一起使用,以添加缺少默认构造函数的类的元素。这可以在用fill(...)初始化后完成。 例子: #include <map> #include <string> #include <iostream> struct Foo { Foo(int n) : m_n(n) {} int m_n; }; int main() { std::map<std::string, Foo> m; // Create a Foo and insert it: Foo foo{ 111 }; // foo.fill(blahblah); m.emplace(std::make_pair<std::string, Foo>("aaa", std::move(foo))); // Verify it was inserted properly: Foo& foo2 = m.at("aaa"); std::cout << foo2.m_n << std::endl; return 0; } 输出: 111 现场演示 请注意,我使用 std::map::at 来验证元素是否已正确插入(使用 operator[] 将无法编译,因为 Foo 缺少默认 ctor)。
如何创建采用 char 或 string 的 map 或 unordered_map 模板?
我尝试编写将 .txt 文件作为参数的代码,读取所述文件,然后获取文本的所有字母(字符)和文本的所有单词(字符串),将它们中的每一个放在地图或一个
c++ std::map operator [] [关闭]中的段错误
gdb 信息: #0 0x00007f53691c1a4a 在 ?? () 来自 /data/services/lib_glibc/lib/libc.so.6 #1 0x0000000000b59a3c in std::char_traits::compare (__n=, __s2= gdb 信息: #0 0x00007f53691c1a4a in ?? () from /data/services/lib_glibc/lib/libc.so.6 #1 0x0000000000b59a3c in std::char_traits<char>::compare (__n=<optimized out>, __s2=<optimized out>, __s1=<optimized out>) at /usr/include/c++/5/bits/char_traits.h:262 #2 std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::compare (__str=..., this=0xc8ce080) at /usr/include/c++/5/bits/basic_string.h:2318 #3 std::operator< <char, std::char_traits<char>, std::allocator<char> > (__rhs=..., __lhs=...) at /usr/include/c++/5/bits/basic_string.h:4989 #4 std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::operator() (this=<optimized out>, __y=..., __x=...) at /usr/include/c++/5/bits/stl_function.h:387 #5 std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_M_lower_bound (this=<optimized out>, __k=..., __y=0x7f5345b40310, __x=0xc8ce060) at /usr/include/c++/5/bits/stl_tree.h:1628 #6 std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::lower_bound (__k=..., this=0x7f5345b40308) at /usr/include/c++/5/bits/stl_tree.h:1091 #7 std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::lower_bound (__x=..., this=0x7f5345b40308) at /usr/include/c++/5/bits/stl_map.h:916 #8 std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::operator[] (__k=..., this=0x7f5345b40308) at /usr/include/c++/5/bits/stl_map.h:479 ... (gdb) f 8 #8 std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::operator[] (__k=..., this=0x7f5345b40308) at /usr/include/c++/5/bits/stl_map.h:479 479 iterator __i = lower_bound(__k); (gdb) i args __k = @0xb8f57a8: {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0xb8f57b8 "bogi-signature"}, _M_string_length = 14, {_M_local_buf = "bogi-signature\000r", _M_allocated_capacity = 7451613697440967010}} this = 0x7f5345b40308 (gdb) f 7 #7 std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::lower_bound (__x=..., this=0x7f5345b40308) at /usr/include/c++/5/bits/stl_map.h:916 916 { return _M_t.lower_bound(__x); } (gdb) i args __x = @0xb8f57a8: {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0xb8f57b8 "bogi-signature"}, _M_string_length = 14, {_M_local_buf = "bogi-signature\000r", _M_allocated_capacity = 7451613697440967010}} this = 0x7f5345b40308 (gdb) f 6 #6 std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::lower_bound (__k=..., this=0x7f5345b40308) at /usr/include/c++/5/bits/stl_tree.h:1091 1091 { return _M_lower_bound(_M_begin(), _M_end(), __k); } (gdb) i args __k = @0xb8f57a8: {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0xb8f57b8 "bogi-signature"}, _M_string_length = 14, {_M_local_buf = "bogi-signature\000r", _M_allocated_capacity = 7451613697440967010}} this = 0x7f5345b40308 (gdb) f 5 #5 std::_Rb_tree<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::_Select1st<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >::_M_lower_bound (this=<optimized out>, __k=..., __y=0x7f5345b40310, __x=0xc8ce060) at /usr/include/c++/5/bits/stl_tree.h:1628 1628 if (!_M_impl._M_key_compare(_S_key(__x), __k)) (gdb) i args this = <optimized out> __k = @0xb8f57a8: {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0xb8f57b8 "bogi-signature"}, _M_string_length = 14, {_M_local_buf = "bogi-signature\000r", _M_allocated_capacity = 7451613697440967010}} __y = 0x7f5345b40310 __x = 0xc8ce060 代码: for (; hIt != cntl->http_request().HeaderEnd(); hIt++) { this->_ctx._header[hIt->first] = hIt->second; } 这是构造函数的代码。 _ctx 是一个成员类,_header 是一个 std::map 成员变量。 hIt->first 和 hIt->second 返回有效的字符串变量。我通过打印 args 确认了这一点。 (用户的deviceid,敏感信息) 我检查了很多,但似乎没有什么是对的
我正在尝试从 openweathermap.org api 中提取天气图标,并使用 u8g2 库(Arduino IDE,C++11)将它们显示在 ESP32 驱动的 OLED 显示器上。 在 openweathermap.org 天气 api 中,16 ...
我想要求澄清一个特定的标准。最近,我开始研究标准的 std::map 容器,我注意到 operator 成员函数有
不能使用 std::map::emplace 插入没有复制构造函数的类的对象
我正在尝试编译以下代码: #包括 #包括 我的班级 { 民众: 我的类():m_cv(){} std::condition_variable m_cv; //只是为了说明...
为什么 std::map(或 std::Rb_tree)中的堆缓冲区溢出
我正在写一个多线程程序。但是,当我运行这段代码时,我遇到了堆缓冲区溢出。 int lock_server_cache_rsm::acquire(lock_protocol::lockid_t lid, std::string id, ...
如果我想加载相对较大的成对文件 并使用 std::map 来存储数据。当我一个一个地加载每个条目并将其插入地图时,插入操作...
第一行代码和第二行代码有什么区别?其中“Vehicle”是用户定义的类。 std::map::iterator 它; 它 = my_map.begin(); while(it!=my_m...
有没有类似于std::map::extract那样从std::list中提取节点的方法?
在我的任务中,我使用了std::list 来维持一个临时的LRU缓存中元素的顺序。所以,其中一个频繁的操作就是把一个列表元素取出来,然后再放回列表中......。
当我试图找出我的程序为什么会出现bug时,我发现。在一个std::map中,当执行搜索时,键是用小于运算符<来比较的。(来自std::map find在......中不能工作。
SWIG c++ python: 如何处理抽象类的shared_ptr的std::map?
如何在python中用SWIG处理抽象方法的映射,从下面的c++代码来看: class A : Base { virtual int f() = 0; }; class B : public A { int f() { return 10 }; }; ...
我遇到了一些问题,这些问题在评论中被指出,所以这是我的新的最小可复制的代码示例;#include #include #include #include