【发布时间】:2013-07-12 08:49:53
【问题描述】:
下面两行有什么区别?
map<int, float> map_data;
map<const int, float> map_data;
【问题讨论】:
标签: c++ key language-lawyer key-value stdmap
下面两行有什么区别?
map<int, float> map_data;
map<const int, float> map_data;
【问题讨论】:
标签: c++ key language-lawyer key-value stdmap
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的情况下,内部密钥类型是仍然非constint:
std::map<const int, float>::key_type => const int
std::map<int, float>::key_type => int
但是,映射键在语义上是不可变的,并且所有允许直接访问键的映射操作(例如,取消引用迭代器,这会产生 value_type)constify 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>
因此,如果您的实现允许,差异可能在很大程度上对您来说是不可见的。
但情况并非总是如此:标准正式要求您的密钥类型是可复制和可移动的,并且some implementations re-use map nodes;在这些实现下,尝试使用 const 键根本行不通。
【讨论】:
So the difference is largely invisible to you in every way that matters. -- 除非您使用复制/移动键的 stdlib(如 libc++),在这种情况下 const 版本会中断。有关相关讨论,请参阅 lists.cs.uiuc.edu/pipermail/cfe-dev/2011-July/015926.html。
const-ness 问题。 C++14 引入了transparent comparators,它增加了一些复杂性,只是为了让我们保持敏锐:)
如果键是指针,常量键会很有帮助。使用 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;
}
【讨论】:
key_type是const int*时,指针本身不是const,但指向的int是const。
key 已经是const,所以在这种情况下写const 是多余的。输入元素后,其key 无法更改。
如 cmets 中所述,两条线之间存在 差异。例如,如果您编写一个接受map<const int, int> 的函数,则不能将map<int, int> 传递给它,因为它们是不同的类型。
但请注意,尽管它们是不同的类型,但它们的行为相同,因为映射中的键无论如何都是 const...
所以总而言之..唯一的区别是它们是两种不同的类型,你不应该关心其他任何事情。
【讨论】:
std::map 的接口将密钥类型公开为const,但这并不意味着这两个模板实例与此答案可能暗示的相同。 std::map<const int, float> 和 std::map<int, float> 是 different types。
key_type 实际上仍然是 int。
虽然您的应用程序的行为通常是相同的,但它会对您可能使用的某些编译器产生影响。更具体的例子是什么让我首先来到这个页面:
使用 gnu 工具包将映射显式指定为map<const key, value> 成功构建;
但是它会导致 Studio12 Solaris x86 版本崩溃。
map<key, value> 在两者上都成功构建。应用程序的行为没有改变。
【讨论】:
std::map::insert 有多个声明。
不同之处在于第二个变体将地图的键类型设置为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 指的是一个常量,一旦定义,就不能改变......非 const 键会发生变化......甚至不能改变,只是在 const (一旦定义),并且“更改”可能会或可能不会发生在非常量的东西中。
【讨论】:
const 设置后无法更改。是的,根据文档和其他答案,您应该记住key 已经是const。
链接:http://www.cplusplus.com/reference/map/map/ 链接:http://en.cppreference.com/w/cpp/container/map
【讨论】: