无序地图 - 使用const键获取值
Unordered Map - get value with const key
我有一个无序的地图,该地图将指针用于自定义对象作为键。由于某种原因,只有在密钥不是const的情况下,使用密钥查找值。
这是一个示例(用std::string
作为自定义对象的替补):
std::unordered_map<std::string*, int> my_map;
std::string key {"test"};
const std::string const_key {"test2"};
auto value = my_map.at(&key); // this works as expected
auto other_value = my_map.at(&const_key); // this doesn't compile
error: invalid conversion from 'const string* {aka const std::__cxx11::basic_string<char>*}'
to 'std::unordered_map<std::__cxx11::basic_string<char>*, int>::key_type
{aka std::__cxx11::basic_string<char>*}' [-fpermissive]
为什么查找需要指针为非const?
编写&const_key
时,将其评估为const std::string *
,但是您的地图将std::string *
用作密钥类型。
"地址到字符串"answers" const"字符串的地址之间存在区别。因此,这些被认为是不同的类型,您不能互换使用它们。
P.S。无法将其写为评论,因此将其发布为答案。
以为我会提供更多的理由(我遇到了同样的问题...咕umbl咕cra咕(Grumble Grumble)。
考虑以下代码:
template <typename T>
void f(T t) { *t += 1; }
int main() {
const int x = 0;
//f<int*>(&x); //error: no matching function for call to ‘f<int*>(const int*)’
//f(&x); //error: assignment of read-only location ‘* t’
int y = 0;
f<int*>(&y); //okay, what we're "supposed" to do
int * const z_p = &y;
f(z_p); //okay, we'll copy z_p by value and modify y
}
在此(有点最小)的示例中,我们可以清楚地看到为什么我们不能将const int *
作为函数f(int *)
的参数。如果这样做,我们可以修改它(不好)。这涵盖了no matching function call
,但是在第二种情况下,我们可以毫无问题地扣除模板扣除,但是当我们尝试修改价值时撞到墙(这不是模板功能错误,您使用了错误!)第三种情况是无聊且期待,我在第四案中扔了,只是为了提醒那些像我这样的人混淆了有趣的指针类型的人。
如果您确定您要调用的功能不会改变您的东西,或者您是一个神秘的国际人,那么总会有选择您的指针。
f<int*>((int*)&x); //that's just lazy
f<int*>(const_cast<int*>(&x)); //that's just crazy
在此特定示例中,上述代码的结果不确定。我用g++ --std=c++14 -g -O0 -Wall
在计算机上运行它,并得到了我的预期,x
的值并没有改变。今天,我们正在处理这种情况,发现由于这是不确定的行为,因此允许编译器优化从对象代码中读取的const值。请注意,X仍然存在于堆栈上,您可以像其他任何内容一样修改内存中的位置,但是当您阅读它时,初始值可能只会由编译器给出。最后,如果将X的定义移至全局范围,那么如果您抛弃const-并修改内存中的位置,则很可能会有一个segfault。
通常,我发现混乱有些合理,因为std::unordered_map<Key,T>::value_type
是std::pair<const Key, T>
(https://en.cppreference.com/w/cpp/container/unordered_map)。在我的脑海中,我有点想:"哦,那么我就可以将const推到那里,一切都可以解决。"然后,我找到了这篇文章,并抓了一秒钟,想到了上述示例,并再次发现该语言保护了我免受我有趣的自我的侵害。叹气...
有关此事的更多阅读,请参见:https://en.cppreference.com/w/cpp/language/template_argument_deduction。
该地图称为
std::unordered_map<std::string*, int> my_map;
^^^^^^^^^^^^
您正在使用类型const std::string *
at
auto other_value = my_map.at(&const_key);
^^^^^^^^^^
从类型const std::string *
到类型std::string *
。
您可以例如声明地图
std::unordered_map<const std::string *, int> my_map;
,在这种情况下,可以使用参数std::string *
和const std::string *
。
- 如果 const 不分配内存,为什么我可以获取 const 的地址?
- 为什么相同的函数签名只有区别,另一个通过 const 获取参数是重新定义?
- 延长函数的寿命延长 由 const& 获取参数并由 const& 返回
- 从本机代码返回"const char*"并在java中获取"字符串"
- 使用const_cast const-ref getter 实现引用获取器的陷阱
- 转换为std :: string并在一行中获取const char *
- 无序地图 - 使用const键获取值
- 获取const lvalue参考的地址是合法的吗?
- 使用 Visual Studio 2013 直接从 std::ostringstream 获取 const char *
- 如何从"const int i"获取i的真实地址
- 如何在不复制或查找的情况下获取 const 字符串流缓冲区的长度?
- 如何在cocos2dx中获取静态const int三维数组长度
- 如何获取对象的const引用并使用该引用更改对象(使用const_cast)
- 如何获取boost::any保存的数据的const引用
- 如何使用用户定义的对象从priority_queue中获取非const顶级元素
- 获取模板类型的基类型(移除const/reference等)
- C++ 为什么 Const& 可以获取 const 值?
- 通过指针获取修饰char*和char const*:很好的实践
- 获取对字符串的子字符串的const访问
- 基于范围的循环:通过值或对const的引用获取项