常量键和非常量键有什么区别
What is difference between const and non const key?
以下两行有什么区别?
map<int, float> map_data;
map<const int, float> map_data;
-
int
和const int
是两种不同的类型。 -
同样,
std::map<int, float>
和std::map<const int, float>
是不同的类型。
在某种程度上,std::map<const int, float>
和std::map<int, float>
之间的差异类似于std::map<int, float>
和std::map<std::string, float>
之间的差异;您将获得每个地图类型的新地图类型。
在非const
情况下,内部密钥类型仍然是非const
int
:
std::map<const int, float>::key_type => const int
std::map<int, float>::key_type => int
但是,映射键在语义上是不可变的,并且所有允许直接访问键的映射操作(例如,取消引用迭代器,这会产生value_type
(const
化key_type
:
std::map<const int, float>::value_type => std::pair<const int, float>
std::map<int, float>::value_type => std::pair<const int, float>
因此,如果您的实现允许,那么在各个重要方面,差异可能在很大程度上对您来说是不可见的。
然而,情况并非总是如此:该标准正式要求你的密钥类型是可复制和可移动的,并且一些实现重用map节点;在这些实现下,尝试使用const
键根本行不通。
密钥已经const
,所以在这种情况下写const
是多余的。输入元素后,无法更改其key
。
编辑:
正如评论中提到的,两行之间存在差异。例如,如果您编写一个接受 map<const int, int>
的函数,则不能map<int, int>
传递给它,因为它们是不同的类型。
但请注意,尽管它们是不同的类型,但它们的行为相同,因为地图中的键无论如何都是const
......
所以总而言之..唯一的区别是它们是两种不同的类型,你不应该关心其他任何事情。
不同之处在于第二个变体会将映射的键类型设置为 const int
。从"可修改性"的角度来看,这是多余的,因为映射已经将其键存储为const
对象。
但是,这也可能导致这两个映射的行为出现意外且不明显的差异。C++为类型 T
编写的模板专用化不同于为类型 const T
编写的专用化。这意味着上述两个版本的地图最终可能会使用取决于密钥类型的各种"卫星"模板的不同专业化。一个例子是键比较器谓词。第一个将使用std::less<int>
而第二个将使用std::less<const int>
。通过利用这种差异,您可以轻松地制作这些地图以不同的顺序对它们的元素进行排序。
像这样的问题在新的 C++11 容器中更为明显,例如 std::unordered_map
. std::unordered_map<const int, int>
甚至不会编译,因为它会尝试使用std::hash<const int>
专用化来散列密钥。标准库中不存在这种专业化。
const
一旦设置就无法更改。是的,根据文档和其他答案,您应该记住key
已经const
了。
链接: http://www.cplusplus.com/reference/map/map/链接: http://en.cppreference.com/w/cpp/container/map
虽然应用程序的行为通常是相同的,但它会对您可能使用的某些编译器产生影响。首先将我带到此页面的更具体示例:
显式指定映射,因为map<const key, value>
使用 gnu 工具包成功构建;
但是,它使Studio12 Solaris x86版本崩溃。
map<key, value>
成功地建立在两者之上。应用程序的行为保持不变。
如果 Const 键是指针,则这些键会很有帮助。使用 const 键不会让您在访问键时修改指向的对象,请考虑以下事项:
#include <map>
#include <string>
int glob = 10;
int main() {
std::map<const int*, std::string> constKeyMap { { &glob, "foo"} };
std::map<int*, std::string> keyMap { { &glob, "bar" } };
for(const auto& kv : keyMap) { *(kv.first) = 20; }; // glob = 20
for(const auto& kv : constKeyMap) { *(kv.first) = 20; }; // COMPILE ERROR
return 0;
}
常量是指一个常量,一旦定义,就无法更改......非常量键可能会发生变化...或者甚至不能改变,只是在 const 中保证"没有变化"(一旦定义(,而"变化"可能会也可能不会发生在非 const 的东西中。
- #定义c-预处理器常量..我做错了什么
- 什么时候在C++中返回常量引用是个好主意
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 返回常量对象引用 (getter) 和仅返回字符串有什么区别?
- C 中的常量限定符和 C++ 中的常量限定符有什么区别?
- 常量公共成员有什么问题?
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 什么时候可以使用常量装饰调用我的重载函数?
- 使用什么代替"静态常量 TCHAR *"
- 常量字符*的性质是什么?
- 初始化不是整数的巨大常量多维数组的最佳方法是什么?
- 第二个常量在运算符函数中做什么?
- 常量成员和没有setter的私有成员之间有什么区别
- 什么是常量指针常量引用类型的参数?(const X* const & p)
- C++:允许临时对象调用非常量成员函数的设计理念是什么?
- 从模块导出全局常量的正确方法是什么?
- 有没有办法声明一个公共静态常量,该常量将使用 constexpr 在源文件中定义(有什么区别)?
- 有什么区别 - 常量 int x = 5000;和常量整数 x = 50'00;在C++?
- 出于什么原因,有必要将常量左值引用绑定到右值?
- 什么是可变常量?