const和non const key有什么区别?


Answers:


65
  • intconst 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>

因此,如果您的实现允许,那么在所有重要方面,差异可能几乎对您几乎是看不见的。

不过,情况并非总是如此:标准正式要求您的密钥类型是可复制和可移动的,并且某些实现会重用地图节点;在这些实现下,尝试使用const密钥根本行不通。


1
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
mitchnull

@mitchnull是的,很好。(顺便说一句!)
Lightness比赛于

@LightnessRacesinOrbit“标准正式要求您的密钥类型是可复制和移动的”。关于可移动性,我找不到我拥有的C ++标准副本,请提供参考编号或部分编号吗?
贝伦

这是一个很好的答案,最终澄清了const我在使用地图时遇到的整个问题。C ++ 14引入了透明的比较器,这些透明的比较器增加了一些复杂度,只是为了让我们保持敏锐:)
vsoftco

啊,谢谢您确认不允许键为const。我希望我的钥匙是一成不变的,这让我发疯了-_-
Noel Widmer

36

关键的是已经const,所以它是多余的写const在这种情况下。输入元素后,将key无法更改。


编辑

正如在评论中提到的,两条线之间的区别。例如,如果编写一个接受函数,map<const int, int>map<int, int>由于它们是不同的类型,因此无法传递给它。

但是请注意,尽管它们是不同的类型,但是它们的行为相同,因为映射中的键始终是const...

因此,总而言之。唯一的区别是它们是两种不同的类型,您无需关心其他任何事情。


18
这(完全)不正确。接口std::map将键类型公开为const,但这并不意味着这两个模板实例与该答案可能暗示的相同。std::map<const int, float>std::map<int, float>不同的类型
jrok 2013年

1
@jrok是正确的,而答案不是。该key_type是实际上还是int在前者的情况下。
Lightness Races in Orbit

6
@ johnmac2332:让这成为一个很快的课程吧!=完美,并赞扬!=正确。
Lightness Races in Orbit 2013年

1
@ johnmac2332快速和快速的答案应该受到高度赞赏。这是Stackoverflow优于其他网站的质量之一。OP可以在评论部分中进一步查询。如果他说谢谢意味着他可能会得到答案。
Grijesh Chauhan

2
没有人是完美的,我们每个人都会犯错并相互学习。我们在这里学习和帮助:)
Maroun

8

不同之处在于第二个变体会将地图的键类型设置为const int。从“可修改性”的角度来看,这是多余的,因为地图已经将其键存储为const对象。

但是,这也会导致这两个地图的行为出现意料之外的差异。在C ++中,为type编写的模板专业化与为typeT编写的专业化不同const T。这意味着地图的以上两个版本最终可能会使用取决于密钥类型的各种“卫星”模板的不同专长。关键比较器谓词就是一个例子。第一个将使用,std::less<int>而第二个将使用std::less<const int>。通过利用这种差异,您可以轻松地使这些映射以不同的顺序对它们的元素进行排序。

像这样的问题在C ++ 11等新容器中更加明显std::unordered_mapstd::unordered_map<const int, int>甚至不会编译,因为它将尝试使用std::hash<const int>特殊化方法对密钥进行哈希处理。这样的专业化在标准库中不存在。



2

尽管您的应用程序的行为通常是相同的,但对于您可能使用的某些编译器却有所不同。首先让我进入此页面的更具体的示例:

map<const key, value>使用gnu工具包成功将地图明确指定为;

但是,它使Studio12 Solaris x86构建崩溃。


map<key, value>两者都成功构建。应用程序的行为不变。


“崩溃”以什么方式?
2013年

@LightnessRacesinOrbit它抱怨std::map::insert有多个声明。
blgt

是的,正如我上文所述:它对编译器有所不同。
blgt

通常,当我们说“崩溃”时,是指进程的意外和不正常的运行时终止。编译器崩溃很少发生,但确实会发生(特别是具有新的语言功能),并且本质上非常严重(随着构建结果的发展)。
2013年

它使我的构建崩溃,而不是应用程序崩溃。我在滥用术语吗?
blgt

0

如果键是指针,则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;
}

1
key_typeisconst int*为时,指针本身不是const,但指向的int是const。
lrineau 2014年

-1

const指的是一个常量,一旦定义,就不能再更改...非const键会发生变化...甚至无法更改,只是const(一旦定义)就保证了“不变” ,并且在非const填充中可能会或可能不会发生“更改”。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.